From 02da7b0aa62bd0623c538264a4ccd7da8dd664f3 Mon Sep 17 00:00:00 2001 From: Florian Henkes Date: Tue, 8 Oct 2024 17:56:27 +0200 Subject: [PATCH] Bug fix error calculation for combined fits --> nested AD not supported yet --- Project.toml | 4 ++++ src/LegendSpecFits.jl | 2 ++ src/aoefit_combined.jl | 50 ++++++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/Project.toml b/Project.toml index 4863d0bf..a4417202 100644 --- a/Project.toml +++ b/Project.toml @@ -22,9 +22,11 @@ LinearRegression = "92481ed7-9fb7-40fd-80f2-46fd0f076581" LsqFit = "2fda8390-95c7-5789-9bda-21331edee243" Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" Measures = "442fdcdd-2543-5da2-b0f3-8c86c306513e" +Optim = "429524aa-4258-5aef-a3af-852621145aeb" Optimization = "7f7a1694-90dd-40f0-9382-eb1efda571ba" OptimizationBBO = "3e6eede4-6085-4f62-9a71-46d9bc1eb92b" OptimizationNLopt = "4e6fcdb7-1186-4e1f-a706-475e75c168bb" +OptimizationOptimJL = "36348300-93cb-4f02-beb5-3c3902f8871e" PropDicts = "4dc08600-4268-439e-8673-d706fafbb426" RadiationSpectra = "4f207c7e-01da-51d7-a1a0-c8c06dd1d883" Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" @@ -66,9 +68,11 @@ LinearRegression = "0.2" LsqFit = "0.14, 0.15" Measurements = "2" Measures = "0.3" +Optim = "1" Optimization = "3, 4" OptimizationBBO = "0.3" OptimizationNLopt = "0.2" +OptimizationOptimJL = "0.3" PropDicts = "0.2" RadiationSpectra = "0.5.11" Random = "1" diff --git a/src/LegendSpecFits.jl b/src/LegendSpecFits.jl index 398096c6..278042e6 100644 --- a/src/LegendSpecFits.jl +++ b/src/LegendSpecFits.jl @@ -25,9 +25,11 @@ using LsqFit using Measurements using Measurements: value as mvalue using Measurements: uncertainty as muncert +using Optim using Optimization using OptimizationBBO using OptimizationNLopt +using OptimizationOptimJL using PropDicts using RadiationSpectra using Roots diff --git a/src/aoefit_combined.jl b/src/aoefit_combined.jl index debd8c75..06bea9ed 100644 --- a/src/aoefit_combined.jl +++ b/src/aoefit_combined.jl @@ -105,7 +105,7 @@ function fit_single_aoe_compton_with_fixed_μ_and_σ(h::Histogram, μ::Number, end # This function calculates the same thing as fit_single_aoe_compton_with_fixed_μ_and_σ, but just returns the value of the negative log-likelihood -function neg_log_likelihood_single_aoe_compton_with_fixed_μ_and_σ(h::Histogram, μ::Number, σ::Number, ps::NamedTuple; fit_func::Symbol = :f_fit, background_center::Union{Real,Nothing} = μ) +function neg_log_likelihood_single_aoe_compton_with_fixed_μ_and_σ(h::Histogram, μ::Real, σ::Real, ps::NamedTuple; fit_func::Symbol = :f_fit, background_center::Union{Real,Nothing} = μ, optimize::Bool=true) # create pseudo priors pseudo_prior = get_aoe_pseudo_prior(h, ps, fit_func; @@ -126,14 +126,18 @@ function neg_log_likelihood_single_aoe_compton_with_fixed_μ_and_σ(h::Histogram end # MLE - optf = OptimizationFunction((u, p) -> ((-) ∘ f_loglike ∘ inverse(f_trafo))(u), AutoForwardDiff()) - optpro = OptimizationProblem(optf, v_init, []) - res = solve(optpro, Optimization.LBFGS(), maxiters = 3000, maxtime=optim_time_limit) + if optimize + optf = OptimizationFunction((u, p) -> ((-) ∘ f_loglike ∘ inverse(f_trafo))(u), AutoForwardDiff()) + optpro = OptimizationProblem(optf, v_init, []) + res = solve(optpro, Optimization.LBFGS(), maxiters = 3000, maxtime=optim_time_limit) - converged = (res.retcode == ReturnCode.Success) - if !converged @warn "Fit did not converge" end + converged = (res.retcode == ReturnCode.Success) + if !converged @warn "Fit did not converge" end - return res.objective + return res.objective + else + return f_loglike(merge((μ = μ, σ = σ), ps)) + end end """ @@ -236,6 +240,19 @@ function fit_aoe_compton_combined(peakhists::Vector{<:Histogram}, peakstats::Str if uncertainty && converged + # create loglikehood function for single hist + function _get_neg_log_likehood(e::Real, h::Histogram, vi::NamedTuple) + # get fit function with background center + fit_function = get_aoe_fit_functions(; background_center = f_aoe_mu(e, (v_ml.μA, v_ml.μB)))[fit_func] + + # create loglikehood function + f_loglike = let f_fit=fit_function, h=h + v -> hist_loglike(x -> x in Interval(extrema(h.edges[1])...) ? f_fit(x, v) : 0, h) + end + - f_loglike(vi) + end + + # create full loglikehood function f_loglike_array = array -> begin pars = array_to_tuple(array, v_ml) @@ -246,18 +263,19 @@ function fit_aoe_compton_combined(peakhists::Vector{<:Histogram}, peakstats::Str # get histogram and peakstats h = peakhists[i] - ps = peakstats[i] + vi = v_results[i] e = ustrip(compton_bands[i]) μ = f_aoe_mu(e, (pars.μA, pars.μB)) σ = f_aoe_sigma(e, (pars.σA, pars.σB)) + + neg_log_likelihoods[i] = _get_neg_log_likehood(e, h, merge(mvalue(vi), (μ = μ, σ = σ))) # fit peak - try - neg_log_likelihoods[i] = neg_log_likelihood_single_aoe_compton_with_fixed_μ_and_σ(h, μ, σ, ps; fit_func=fit_func) - catch e - @warn "Error fitting band $(compton_bands[i]): $e" - continue - end + # try + # catch e + # @warn "Error fitting band $(compton_bands[i]): $e" + # continue + # end end return sum(neg_log_likelihoods) end @@ -294,7 +312,7 @@ function fit_aoe_compton_combined(peakhists::Vector{<:Histogram}, peakstats::Str @debug "σB: $(v_ml.σB) ± $(v_ml_err.σB)" result = merge(NamedTuple{keys(v_ml)}([measurement(v_ml[k], v_ml_err[k]) for k in keys(v_ml)]...), - (gof = (pvalue = pval, chi2 = chi2, dof = dof, covmat = param_covariance, + (gof = (converged = converged, pvalue = pval, chi2 = chi2, dof = dof, covmat = param_covariance, residuals = residuals, residuals_norm = residuals_norm),) #, bin_centers = bin_centers),) ) else @@ -304,7 +322,7 @@ function fit_aoe_compton_combined(peakhists::Vector{<:Histogram}, peakstats::Str @debug "σA: $(v_ml.σA)" @debug "σB: $(v_ml.σB)" - result = merge(v_ml, ) + result = merge(v_ml, (gof = (converged = converged, ), )) end # Add same fields to result as fit_aoe_corrections