From 2b0f965f15ed1691d34d02f421f10bac6d25ab10 Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Mon, 25 Aug 2025 11:48:49 +0200 Subject: [PATCH] provide a breadcrumb when spline interpolation fails during profiling --- issues/794/Project.toml | 5 +++++ issues/794/main.jl | 13 +++++++++++++ src/profile/sigmapr.jl | 11 +++++++++-- src/profile/vcpr.jl | 11 ++++++++--- 4 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 issues/794/Project.toml create mode 100644 issues/794/main.jl diff --git a/issues/794/Project.toml b/issues/794/Project.toml new file mode 100644 index 000000000..a7ca96922 --- /dev/null +++ b/issues/794/Project.toml @@ -0,0 +1,5 @@ +[deps] +BSplineKit = "093aae92-e908-43d7-9660-e50ee39d5a0a" +CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +MixedModels = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316" +MixedModelsDatasets = "7e9fb7ac-9f67-43bf-b2c8-96ba0796cbb6" diff --git a/issues/794/main.jl b/issues/794/main.jl new file mode 100644 index 000000000..9c074931d --- /dev/null +++ b/issues/794/main.jl @@ -0,0 +1,13 @@ +using CSV +using MixedModels +using MixedModelsDatasets: dataset +x = CSV.read(download("https://gist.githubusercontent.com/yjunechoe/af4a8dd3e2b0343fe3818e93dba8c81d/raw/x.csv"), Table); +m = fit(MixedModel, @formula(y ~ x1 * x2 + (1 | g)), x) + +profile(m; threshold=4) # works + +profile(m; threshold=3) + +s = lmm(@formula(reaction ~ 1 + days + (1 + days| subj)), dataset(:sleepstudy)) + +profile(s; threshold=3) diff --git a/src/profile/sigmapr.jl b/src/profile/sigmapr.jl index 3336ebe52..186cb5051 100644 --- a/src/profile/sigmapr.jl +++ b/src/profile/sigmapr.jl @@ -33,6 +33,7 @@ end profileσ(m::LinearMixedModel, tc::TableColumns; threshold=4) Return a Table of the profile of `σ` for model `m`. The profile extends to where the magnitude of ζ exceeds `threshold`. + !!! note This method is called by `profile` and currently considered internal. As such, it may change or disappear in a future release without being considered breaking. @@ -69,7 +70,13 @@ function profileσ(m::LinearMixedModel{T}, tc::TableColumns{T}; threshold=4) whe updateL!(setθ!(m, θ)) σv = [r.σ for r in tbl] ζv = [r.ζ for r in tbl] - fwd = Dict(:σ => interpolate(σv, ζv, BSplineOrder(4), Natural())) - rev = Dict(:σ => interpolate(ζv, σv, BSplineOrder(4), Natural())) + local fwd, rev + try + fwd = Dict(:σ => interpolate(σv, ζv, BSplineOrder(4), Natural())) + rev = Dict(:σ => interpolate(ζv, σv, BSplineOrder(4), Natural())) + catch + @error "An error occurred while fitting the profile splines for σ. Try adjusting the threshold." + rethrow() + end return (; m, tbl, fwd, rev) end diff --git a/src/profile/vcpr.jl b/src/profile/vcpr.jl index fca28ef55..e20b09c80 100644 --- a/src/profile/vcpr.jl +++ b/src/profile/vcpr.jl @@ -78,9 +78,14 @@ function profileσs!(val::NamedTuple, tc::TableColumns{T}; nzlb=1.0e-8) where {T append!(val.tbl, tbl) ζcol = getproperty(:ζ).(tbl) symcol = gpsym.(tbl) - val.fwd[sym] = interpolate(symcol, ζcol, BSplineOrder(4), Natural()) - issorted(ζcol) && - (val.rev[sym] = interpolate(ζcol, symcol, BSplineOrder(4), Natural())) + try + val.fwd[sym] = interpolate(symcol, ζcol, BSplineOrder(4), Natural()) + issorted(ζcol) && + (val.rev[sym] = interpolate(ζcol, symcol, BSplineOrder(4), Natural())) + catch + @error "An error occurred while fitting the profile splines for the variance components. Try adjusting the threshold." + rethrow() + end end end copyto!(final, initial)