Skip to content

Commit eb039a2

Browse files
author
Alexey Stukalov
committed
test_fitmeasures(): refactor/simplify
1 parent aa29cdb commit eb039a2

4 files changed

Lines changed: 42 additions & 139 deletions

File tree

test/examples/helper.jl

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -49,34 +49,40 @@ function test_hessian(model, params; rtol = 1e-4, atol = 0)
4949
@test hessian true_hessian rtol = rtol atol = atol
5050
end
5151

52-
fitmeasure_names_ml = Dict(
52+
# map from the SEM.jl name of the fit measure to the lavaan's one
53+
fitmeasure_semjl_to_lavaan = Dict(
5354
:AIC => "aic",
5455
:BIC => "bic",
5556
:dof => "df",
5657
:χ² => "chisq",
5758
:p_value => "pvalue",
5859
:nparams => "npar",
5960
:RMSEA => "rmsea",
60-
)
61-
62-
fitmeasure_names_ls = Dict(
63-
:dof => "df",
64-
:χ² => "chisq",
65-
:p_value => "pvalue",
66-
:nparams => "npar",
67-
:RMSEA => "rmsea",
61+
:CFI => "cfi",
6862
)
6963

7064
function test_fitmeasures(
71-
measures,
65+
fitted::SemFit,
7266
measures_lav;
67+
fitmeasures::AbstractVector = SEM.DEFAULT_FIT_MEASURES,
68+
fitted_baseline::Union{SemFit, Nothing} = nothing,
7369
rtol = 1e-4,
7470
atol = 0,
75-
fitmeasure_names = fitmeasure_names_ml,
7671
)
77-
@testset "$name" for (key, name) in pairs(fitmeasure_names)
78-
measure_lav = measures_lav.x[findfirst(==(name), measures_lav[!, 1])]
79-
@test measures[key] measure_lav rtol = rtol atol = atol
72+
@testset "$fn" for fn in fitmeasures
73+
name = Symbol(fn)
74+
# FIML CFI requires the baseline model
75+
measure =
76+
fn != CFI || isnothing(fitted_baseline) ? fn(fitted) :
77+
fn(fitted, fitted_baseline)
78+
lav_name = fitmeasure_semjl_to_lavaan[name]
79+
lav_ix = findfirst(==(lav_name), measures_lav[!, 1])
80+
if isnothing(lav_ix)
81+
@test ismissing(measure)
82+
else
83+
measure_lav = measures_lav.x[lav_ix]
84+
@test measure measure_lav rtol = rtol atol = atol
85+
end
8086
end
8187
end
8288

test/examples/multigroup/build_models.jl

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,7 @@ end
5252

5353
@testset "fitmeasures/se_ml" begin
5454
solution_ml = fit(semoptimizer, model_ml_multigroup)
55-
test_fitmeasures(
56-
fit_measures(solution_ml),
57-
solution_lav[:fitmeasures_ml];
58-
rtol = 1e-2,
59-
atol = 1e-7,
60-
)
61-
test_fitmeasures(
62-
Dict(:CFI => CFI(solution_ml)),
63-
solution_lav[:fitmeasures_ml];
64-
fitmeasure_names = Dict(:CFI => "cfi"),
65-
)
55+
test_fitmeasures(solution_ml, solution_lav[:fitmeasures_ml]; rtol = 1e-2, atol = 1e-7)
6656

6757
update_se_hessian!(partable, solution_ml)
6858
test_estimates(
@@ -122,17 +112,7 @@ end
122112

123113
@testset "fitmeasures/se_ml | sorted" begin
124114
solution_ml = fit(semoptimizer, model_ml_multigroup)
125-
test_fitmeasures(
126-
fit_measures(solution_ml),
127-
solution_lav[:fitmeasures_ml];
128-
rtol = 1e-2,
129-
atol = 1e-7,
130-
)
131-
test_fitmeasures(
132-
Dict(:CFI => CFI(solution_ml)),
133-
solution_lav[:fitmeasures_ml];
134-
fitmeasure_names = Dict(:CFI => "cfi"),
135-
)
115+
test_fitmeasures(solution_ml, solution_lav[:fitmeasures_ml]; rtol = 1e-2, atol = 1e-7)
136116

137117
update_se_hessian!(partable_s, solution_ml)
138118
test_estimates(
@@ -221,18 +201,7 @@ end
221201

222202
@testset "fitmeasures/se_ls" begin
223203
solution_ls = fit(semoptimizer, model_ls_multigroup)
224-
test_fitmeasures(
225-
fit_measures(solution_ls),
226-
solution_lav[:fitmeasures_ls];
227-
fitmeasure_names = fitmeasure_names_ls,
228-
rtol = 1e-2,
229-
atol = 1e-5,
230-
)
231-
test_fitmeasures(
232-
Dict(:CFI => CFI(solution_ls)),
233-
solution_lav[:fitmeasures_ls];
234-
fitmeasure_names = Dict(:CFI => "cfi"),
235-
)
204+
test_fitmeasures(solution_ls, solution_lav[:fitmeasures_ls]; rtol = 1e-2, atol = 1e-5)
236205

237206
@suppress update_se_hessian!(partable, solution_ls)
238207
test_estimates(
@@ -319,18 +288,14 @@ if !isnothing(specification_miss_g1)
319288

320289
@testset "fitmeasures/se_fiml" begin
321290
solution = fit(semoptimizer, model_ml_multigroup)
291+
solution_varonly = fit(semoptimizer, model_ml_varonly)
322292
test_fitmeasures(
323-
fit_measures(solution),
293+
solution,
324294
solution_lav[:fitmeasures_fiml];
295+
fitted_baseline = solution_varonly,
325296
rtol = 1e-3,
326297
atol = 0,
327298
)
328-
solution_varonly = fit(semoptimizer, model_ml_varonly)
329-
test_fitmeasures(
330-
Dict(:CFI => CFI(solution, solution_varonly)),
331-
solution_lav[:fitmeasures_fiml];
332-
fitmeasure_names = Dict(:CFI => "cfi"),
333-
)
334299
update_se_hessian!(partable_miss, solution)
335300
test_estimates(
336301
partable_miss,

test/examples/political_democracy/by_parts.jl

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -90,12 +90,7 @@ end
9090

9191
@testset "fitmeasures/se_ml" begin
9292
solution_ml = fit(semoptimizer, model_ml)
93-
test_fitmeasures(fit_measures(solution_ml), solution_lav[:fitmeasures_ml]; atol = 1e-3)
94-
test_fitmeasures(
95-
Dict(:CFI => CFI(solution_ml)),
96-
solution_lav[:fitmeasures_ml];
97-
fitmeasure_names = Dict(:CFI => "cfi"),
98-
)
93+
test_fitmeasures(solution_ml, solution_lav[:fitmeasures_ml]; atol = 1e-3)
9994

10095
update_se_hessian!(partable, solution_ml)
10196
test_estimates(
@@ -109,14 +104,7 @@ end
109104

110105
@testset "fitmeasures/se_ls" begin
111106
solution_ls = fit(semoptimizer, model_ls_sym)
112-
fm = fit_measures(solution_ls)
113-
test_fitmeasures(
114-
merge(fm, Dict(:CFI => CFI(solution_ls))),
115-
solution_lav[:fitmeasures_ls];
116-
atol = 1e-3,
117-
fitmeasure_names = merge(fitmeasure_names_ls, Dict(:CFI => "cfi"))
118-
)
119-
@test ismissing(fm[:AIC]) && ismissing(fm[:BIC]) && ismissing(fm[:minus2ll])
107+
test_fitmeasures(solution_ls, solution_lav[:fitmeasures_ls]; atol = 1e-3)
120108

121109
@suppress update_se_hessian!(partable, solution_ls)
122110
test_estimates(
@@ -241,16 +229,7 @@ end
241229

242230
@testset "fitmeasures/se_ml_mean" begin
243231
solution_ml = fit(semoptimizer, model_ml)
244-
test_fitmeasures(
245-
fit_measures(solution_ml),
246-
solution_lav[:fitmeasures_ml_mean];
247-
atol = 1e-3,
248-
)
249-
test_fitmeasures(
250-
Dict(:CFI => CFI(solution_ml)),
251-
solution_lav[:fitmeasures_ml_mean];
252-
fitmeasure_names = Dict(:CFI => "cfi"),
253-
)
232+
test_fitmeasures(solution_ml, solution_lav[:fitmeasures_ml_mean]; atol = 1e-3)
254233

255234
update_se_hessian!(partable_mean, solution_ml)
256235
test_estimates(
@@ -264,14 +243,7 @@ end
264243

265244
@testset "fitmeasures/se_ls_mean" begin
266245
solution_ls = fit(semoptimizer, model_ls)
267-
fm = fit_measures(solution_ls)
268-
test_fitmeasures(
269-
merge(fm, Dict(:CFI => CFI(solution_ls))),
270-
solution_lav[:fitmeasures_ls_mean];
271-
atol = 1e-3,
272-
fitmeasure_names = merge(fitmeasure_names_ls, Dict(:CFI => "cfi")),
273-
)
274-
@test ismissing(fm[:AIC]) && ismissing(fm[:BIC]) && ismissing(fm[:minus2ll])
246+
test_fitmeasures(solution_ls, solution_lav[:fitmeasures_ls_mean]; atol = 1e-3)
275247

276248
@suppress update_se_hessian!(partable_mean, solution_ls)
277249
test_estimates(

test/examples/political_democracy/constructor.jl

Lines changed: 12 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,7 @@ end
100100

101101
@testset "fitmeasures/se_ml" begin
102102
solution_ml = fit(semoptimizer, model_ml)
103-
test_fitmeasures(fit_measures(solution_ml), solution_lav[:fitmeasures_ml]; atol = 1e-3)
104-
test_fitmeasures(
105-
Dict(:CFI => CFI(solution_ml)),
106-
solution_lav[:fitmeasures_ml];
107-
fitmeasure_names = Dict(:CFI => "cfi"),
108-
)
103+
test_fitmeasures(solution_ml, solution_lav[:fitmeasures_ml]; atol = 1e-3)
109104

110105
update_se_hessian!(partable, solution_ml)
111106
test_estimates(
@@ -122,20 +117,7 @@ end
122117

123118
@testset "fitmeasures/se_ls" begin
124119
solution_ls = fit(semoptimizer, model_ls_sym)
125-
fm = fit_measures(solution_ls)
126-
test_fitmeasures(
127-
fm,
128-
solution_lav[:fitmeasures_ls];
129-
atol = 1e-3,
130-
fitmeasure_names = fitmeasure_names_ls,
131-
)
132-
test_fitmeasures(
133-
Dict(:CFI => CFI(solution_ls)),
134-
solution_lav[:fitmeasures_ls];
135-
fitmeasure_names = Dict(:CFI => "cfi"),
136-
)
137-
138-
@test ismissing(fm[:AIC]) && ismissing(fm[:BIC]) && ismissing(fm[:minus2ll])
120+
test_fitmeasures(solution_ls, solution_lav[:fitmeasures_ls]; atol = 1e-3)
139121

140122
@suppress update_se_hessian!(partable, solution_ls)
141123
test_estimates(
@@ -298,16 +280,7 @@ end
298280

299281
@testset "fitmeasures/se_ml_mean" begin
300282
solution_ml = fit(semoptimizer, model_ml)
301-
test_fitmeasures(
302-
fit_measures(solution_ml),
303-
solution_lav[:fitmeasures_ml_mean];
304-
atol = 0.002,
305-
)
306-
test_fitmeasures(
307-
Dict(:CFI => CFI(solution_ml)),
308-
solution_lav[:fitmeasures_ml_mean];
309-
fitmeasure_names = Dict(:CFI => "cfi"),
310-
)
283+
test_fitmeasures(solution_ml, solution_lav[:fitmeasures_ml_mean]; atol = 0.002)
311284

312285
update_se_hessian!(partable_mean, solution_ml)
313286
test_estimates(
@@ -324,19 +297,7 @@ end
324297

325298
@testset "fitmeasures/se_ls_mean" begin
326299
solution_ls = fit(semoptimizer, model_ls)
327-
fm = fit_measures(solution_ls)
328-
test_fitmeasures(
329-
fm,
330-
solution_lav[:fitmeasures_ls_mean];
331-
atol = 1e-3,
332-
fitmeasure_names = fitmeasure_names_ls,
333-
)
334-
@test ismissing(fm[:AIC]) && ismissing(fm[:BIC]) && ismissing(fm[:minus2ll])
335-
test_fitmeasures(
336-
Dict(:CFI => CFI(solution_ls)),
337-
solution_lav[:fitmeasures_ls_mean];
338-
fitmeasure_names = Dict(:CFI => "cfi"),
339-
)
300+
test_fitmeasures(solution_ls, solution_lav[:fitmeasures_ls_mean]; atol = 1e-3)
340301

341302
@suppress update_se_hessian!(partable_mean, solution_ls)
342303
test_estimates(
@@ -410,6 +371,8 @@ if !ismissing(spec_varonly)
410371
loss = SemFIML,
411372
meanstructure = true,
412373
)
374+
else
375+
model_varonly = nothing
413376
end
414377

415378
############################################################################################
@@ -446,19 +409,16 @@ end
446409

447410
@testset "fitmeasures/se_fiml" begin
448411
solution_ml = fit(semoptimizer, model_ml)
412+
solution_varonly =
413+
!isnothing(model_varonly) ? fit(semoptimizer, model_varonly) : nothing
449414
test_fitmeasures(
450-
fit_measures(solution_ml),
415+
solution_ml,
451416
solution_lav[:fitmeasures_fiml];
417+
fitted_baseline = solution_varonly,
418+
fitmeasures = !isnothing(solution_varonly) ? SEM.DEFAULT_FIT_MEASURES :
419+
filter(!=(CFI), SEM.DEFAULT_FIT_MEASURES),
452420
atol = 1e-3,
453421
)
454-
if !ismissing(spec_varonly)
455-
solution_varonly = fit(semoptimizer, model_varonly)
456-
test_fitmeasures(
457-
Dict(:CFI => CFI(solution_ml, solution_varonly)),
458-
solution_lav[:fitmeasures_fiml];
459-
fitmeasure_names = Dict(:CFI => "cfi"),
460-
)
461-
end
462422

463423
update_se_hessian!(partable_mean, solution_ml)
464424
test_estimates(

0 commit comments

Comments
 (0)