1
1
"""
2
- restoreoptsum!(m::LinearMixedModel , io::IO; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps)
3
- restoreoptsum!(m::LinearMixedModel , filename; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps)
2
+ restoreoptsum!(m::MixedModel , io::IO; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps)
3
+ restoreoptsum!(m::MixedModel , filename; atol::Real=0, rtol::Real=atol>0 ? 0 : √eps)
4
4
5
5
Read, check, and restore the `optsum` field from a JSON stream or filename.
6
6
"""
7
+ function restoreoptsum! (m:: MixedModel , filename; kwargs... )
8
+ return open (filename, " r" ) do io
9
+ return restoreoptsum! (m, io; kwargs... )
10
+ end
11
+ end
12
+
7
13
function restoreoptsum! (
8
14
m:: LinearMixedModel{T} , io:: IO ; atol:: Real = zero (T),
9
15
rtol:: Real = atol > 0 ? zero (T) : √ eps (T),
16
+ ) where {T}
17
+ dict = JSON3. read (io)
18
+ ops = restoreoptsum! (m. optsum, dict)
19
+ for (par, obj_at_par) in (:initial => :finitial , :final => :fmin )
20
+ if ! isapprox (
21
+ objective (updateL! (setθ! (m, getfield (ops, par)))), getfield (ops, obj_at_par);
22
+ rtol, atol,
23
+ )
24
+ throw (
25
+ ArgumentError (
26
+ " model at $par does not match stored $obj_at_par within atol=$atol , rtol=$rtol "
27
+ ),
28
+ )
29
+ end
30
+ end
31
+ return m
32
+ end
33
+
34
+ function restoreoptsum! (
35
+ m:: GeneralizedLinearMixedModel{T} , io:: IO ; atol:: Real = zero (T),
36
+ rtol:: Real = atol > 0 ? zero (T) : √ eps (T),
10
37
) where {T}
11
38
dict = JSON3. read (io)
12
39
ops = m. optsum
40
+
41
+ # need to accommodate fast and slow fits
42
+ resize! (ops. initial, length (dict. initial))
43
+ resize! (ops. final, length (dict. final))
44
+
45
+ theta_beta_len = length (m. θ) + length (m. β)
46
+ if length (dict. initial) == theta_beta_len # fast=false
47
+ if length (ops. lowerbd) == length (m. θ)
48
+ prepend! (ops. lowerbd, fill (- Inf , length (m. β)))
49
+ end
50
+ setpar! = setβθ!
51
+ varyβ = false
52
+ else # fast=true
53
+ setpar! = setθ!
54
+ varyβ = true
55
+ if length (ops. lowerbd) != length (m. θ)
56
+ deleteat! (ops. lowerbd, 1 : length (m. β))
57
+ end
58
+ end
59
+ restoreoptsum! (ops, dict)
60
+ for (par, obj_at_par) in (:initial => :finitial , :final => :fmin )
61
+ if ! isapprox (
62
+ deviance (pirls! (setpar! (m, getfield (ops, par)), varyβ), dict. nAGQ),
63
+ getfield (ops, obj_at_par); rtol, atol,
64
+ )
65
+ throw (
66
+ ArgumentError (
67
+ " model at $par does not match stored $obj_at_par within atol=$atol , rtol=$rtol "
68
+ ),
69
+ )
70
+ end
71
+ end
72
+ return m
73
+ end
74
+
75
+ function restoreoptsum! (ops:: OptSummary{T} , dict:: AbstractDict ) where {T}
13
76
allowed_missing = (
14
77
:lowerbd , # never saved, -Inf not allowed in JSON
15
78
:xtol_zero_abs , # added in v4.25.0
@@ -27,7 +90,9 @@ function restoreoptsum!(
27
90
if length (setdiff (allowed_missing, keys (dict))) > 1 # 1 because :lowerbd
28
91
@warn " optsum was saved with an older version of MixedModels.jl: consider resaving."
29
92
end
93
+
30
94
if any (ops. lowerbd .> dict. initial) || any (ops. lowerbd .> dict. final)
95
+ @debug " " ops. lowerbd dict. initial dict. final
31
96
throw (ArgumentError (" initial or final parameters in io do not satisfy lowerbd" ))
32
97
end
33
98
for fld in (:feval , :finitial , :fmin , :ftol_rel , :ftol_abs , :maxfeval , :nAGQ , :REML )
@@ -37,13 +102,6 @@ function restoreoptsum!(
37
102
ops. xtol_rel = copy (dict. xtol_rel)
38
103
copyto! (ops. initial, dict. initial)
39
104
copyto! (ops. final, dict. final)
40
- for (v, f) in (:initial => :finitial , :final => :fmin )
41
- if ! isapprox (
42
- objective (updateL! (setθ! (m, getfield (ops, v)))), getfield (ops, f); rtol, atol
43
- )
44
- throw (ArgumentError (" model m at $v does not give stored $f " ))
45
- end
46
- end
47
105
ops. optimizer = Symbol (dict. optimizer)
48
106
ops. returnvalue = Symbol (dict. returnvalue)
49
107
# compatibility with fits saved before the introduction of various extensions
@@ -59,30 +117,23 @@ function restoreoptsum!(
59
117
else
60
118
[(convert (Vector{T}, first (entry)), T (last (entry))) for entry in fitlog]
61
119
end
62
- return m
63
- end
64
-
65
- function restoreoptsum! (m:: LinearMixedModel{T} , filename; kwargs... ) where {T}
66
- open (filename, " r" ) do io
67
- restoreoptsum! (m, io; kwargs... )
68
- end
120
+ return ops
69
121
end
70
122
71
123
"""
72
- saveoptsum(io::IO, m::LinearMixedModel )
73
- saveoptsum(filename, m::LinearMixedModel )
124
+ saveoptsum(io::IO, m::MixedModel )
125
+ saveoptsum(filename, m::MixedModel )
74
126
75
127
Save `m.optsum` (w/o the `lowerbd` field) in JSON format to an IO stream or a file
76
128
77
129
The reason for omitting the `lowerbd` field is because it often contains `-Inf`
78
130
values that are not allowed in JSON.
79
131
"""
80
- saveoptsum (io:: IO , m:: LinearMixedModel ) = JSON3. write (io, m. optsum)
81
- function saveoptsum (filename, m:: LinearMixedModel )
132
+ saveoptsum (io:: IO , m:: MixedModel ) = JSON3. write (io, m. optsum)
133
+ function saveoptsum (filename, m:: MixedModel )
82
134
open (filename, " w" ) do io
83
135
saveoptsum (io, m)
84
136
end
85
137
end
86
138
87
- # TODO : write methods for GLMM
88
139
# TODO , maybe: something nice for the MixedModelBootstrap
0 commit comments