## ----setup, include=FALSE-----------------------------------------------------
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 8,
                     fig.height = 5.5, out.width = "100%")
library(lvmPlot)
packages <- c("lavaan", "psych", "mirt", "eRm", "mclust", "OpenMx", "semPlot")
available <- setNames(vapply(packages, requireNamespace, logical(1), quietly = TRUE), packages)
.models <- list()
remember_model <- function(name, object, label = "std", input = "fitted object", diagram = "all") {
  .models[[name]] <<- list(object = object, label = label, input = input, diagram = diagram)
}

## ----package-versions, echo=FALSE---------------------------------------------
knitr::kable(data.frame(Package = packages,
  Version = vapply(packages, function(p) {
    if (available[[p]]) as.character(utils::packageVersion(p)) else "Not installed; example not run"
  }, character(1))), row.names = FALSE)

## ----cfa, eval=available[["lavaan"]]------------------------------------------
cfa_model <- '
  visual  =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
  speed   =~ x7 + x8 + x9
'
hs <- lavaan::HolzingerSwineford1939
cfa_fit <- lavaan::cfa(cfa_model, data = hs)
plot_lvm(cfa_fit, diagram = "all", label = "std", stars = FALSE)

## ----cfa-record, include=FALSE, eval=available[["lavaan"]]--------------------
stopifnot(lavaan::lavInspect(cfa_fit, "converged"))
remember_model("cfa", cfa_fit)

## ----sem, eval=available[["lavaan"]]------------------------------------------
sem_model <- '
  visual  =~ x1 + x2 + x3
  textual =~ x4 + x5 + x6
  speed   =~ x7 + x8 + x9
  textual ~ visual
  speed ~ visual + textual
'
sem_fit <- lavaan::sem(sem_model, data = hs)
plot_lvm(sem_fit, diagram = "all", label = "std", stars = FALSE)

## ----sem-record, include=FALSE, eval=available[["lavaan"]]--------------------
stopifnot(lavaan::lavInspect(sem_fit, "converged"))
remember_model("sem", sem_fit)

## ----ordinal, eval=available[["lavaan"]]--------------------------------------
ordinal_data <- hs
items <- paste0("x", 1:9)
for (item in items) {
  ordinal_data[[item]] <- ordered(cut(hs[[item]],
    breaks = stats::quantile(hs[[item]], seq(0, 1, length.out = 5)),
    include.lowest = TRUE))
}
ordinal_fit <- lavaan::cfa(cfa_model, data = ordinal_data, ordered = items)
plot_lvm(ordinal_fit, diagram = "all", label = "std", stars = FALSE)

## ----ordinal-record, include=FALSE, eval=available[["lavaan"]]----------------
stopifnot(lavaan::lavInspect(ordinal_fit, "converged"))
remember_model("ordinal-cfa", ordinal_fit)

## ----growth, eval=available[["lavaan"]]---------------------------------------
growth_model <- '
  i =~ 1*t1 + 1*t2 + 1*t3 + 1*t4
  s =~ 0*t1 + 1*t2 + 2*t3 + 3*t4
'
growth_fit <- lavaan::growth(growth_model, data = lavaan::Demo.growth)
plot_lvm(growth_fit, diagram = "all", label = "est", stars = FALSE)

## ----growth-record, include=FALSE, eval=available[["lavaan"]]-----------------
stopifnot(lavaan::lavInspect(growth_fit, "converged"))
remember_model("growth", growth_fit, "est")

## ----multilevel, eval=available[["lavaan"]]-----------------------------------
twolevel_data <- subset(lavaan::Demo.twolevel, cluster <= 30)
twolevel_model <- '
  level: 1
    fw =~ y1 + y2 + y3
  level: 2
    fb =~ y1 + y2 + y3
'
twolevel_fit <- lavaan::sem(twolevel_model, data = twolevel_data, cluster = "cluster")
plot_lvm(twolevel_fit, diagram = "all", label = "std", stars = FALSE)

## ----multilevel-record, include=FALSE, eval=available[["lavaan"]]-------------
stopifnot(lavaan::lavInspect(twolevel_fit, "converged"))
remember_model("twolevel-cfa", twolevel_fit)

## ----multigroup, eval=available[["lavaan"]]-----------------------------------
group_fit <- lavaan::cfa(cfa_model, data = hs, group = "school",
                        group.equal = "loadings")
group_parameters <- lavaan::parameterEstimates(group_fit, standardized = TRUE)
group_names <- lavaan::lavInspect(group_fit, "group.label")
group_tables <- lapply(seq_along(group_names), function(g) {
  group_parameters[group_parameters$group == g, , drop = FALSE]
})
names(group_tables) <- group_names
plot_lvm(group_tables[[1]], diagram = "all", label = "std", stars = FALSE)
plot_lvm(group_tables[[2]], diagram = "all", label = "std", stars = FALSE)

## ----multigroup-record, include=FALSE, eval=available[["lavaan"]]-------------
stopifnot(lavaan::lavInspect(group_fit, "converged"))
for (g in seq_along(group_tables)) {
  remember_model(paste0("group-", g), group_tables[[g]], input = "group-specific fitted parameter table")
}

## ----efa, eval=available[["psych"]] && available[["lavaan"]]------------------
efa_fit <- psych::fa(hs[paste0("x", 1:9)], nfactors = 3,
                     rotate = "oblimin", fm = "minres")
plot_lvm(efa_fit, diagram = "all", label = "est", stars = FALSE)

## ----efa-record, include=FALSE, eval=available[["psych"]] && available[["lavaan"]]----
remember_model("efa", efa_fit, "est")

## ----irt, eval=available[["mirt"]]--------------------------------------------
irt_data <- mirt::expand.table(mirt::LSAT7)
irt_fit <- mirt::mirt(irt_data, 1, itemtype = "2PL", verbose = FALSE,
                      quadpts = 21L, TOL = 1e-3,
                      technical = list(NCYCLES = 200L))
plot_lvm(irt_fit, diagram = "all", label = "est", stars = FALSE)

## ----irt-record, include=FALSE, eval=available[["mirt"]]----------------------
stopifnot(mirt::extract.mirt(irt_fit, "converged"))
remember_model("irt-2pl", irt_fit, "est")

## ----rasch, eval=available[["eRm"]]-------------------------------------------
rasch_fit <- eRm::RM(eRm::raschdat1[, 1:6])
plot_lvm(rasch_fit, diagram = "all", label = "est", stars = FALSE)

## ----rasch-record, include=FALSE, eval=available[["eRm"]]---------------------
remember_model("rasch", rasch_fit, "est")

## ----mixture, eval=available[["mclust"]]--------------------------------------
library(mclust)
profile_fit <- mclust::Mclust(iris[, 1:4], G = 3, modelNames = "EII", verbose = FALSE)
plot_lvm(profile_fit, diagram = "all", label = "none")

## ----mixture-record, include=FALSE, eval=available[["mclust"]]----------------
remember_model("gaussian-mixture", profile_fit, "none")

## ----openmx, eval=available[["OpenMx"]] && available[["lavaan"]]--------------
variables <- c("x1", "x2", "x3")
mx_fit <- OpenMx::mxModel("one_factor", type = "RAM",
  manifestVars = variables, latentVars = "F",
  OpenMx::mxPath(from = "F", to = variables, arrows = 1,
                free = c(FALSE, TRUE, TRUE), values = c(1, .8, .8)),
  OpenMx::mxPath(from = variables, arrows = 2, free = TRUE, values = 1),
  OpenMx::mxPath(from = "F", arrows = 2, free = TRUE, values = 1),
  OpenMx::mxData(observed = stats::cov(hs[variables]), type = "cov", numObs = nrow(hs)))
mx_fit <- OpenMx::mxRun(mx_fit, silent = TRUE)
plot_lvm(mx_fit, diagram = "all", label = "est", stars = FALSE)

## ----openmx-record, include=FALSE, eval=available[["OpenMx"]] && available[["lavaan"]]----
stopifnot(mx_fit$output$status$code == 0)
remember_model("openmx-ram", mx_fit, "est")

## ----semplot, eval=available[["semPlot"]] && available[["lavaan"]]------------
semplot_object <- semPlot::semPlotModel(cfa_fit)
plot_lvm(semplot_object, diagram = "all", label = "est", stars = FALSE)

## ----semplot-record, include=FALSE, eval=available[["semPlot"]] && available[["lavaan"]]----
remember_model("semplot-bridge", semplot_object, "est", input = "semPlotModel converted from a fitted CFA")

## ----bifactor-----------------------------------------------------------------
bifactor_paths <- data.frame(
  lhs = c(rep("g", 9), rep(c("s1", "s2", "s3"), each = 3)),
  op = "=~", rhs = rep(paste0("x", 1:9), 2))
plot_lvm(bifactor_paths, diagram = "all", label = "none")

## ----bifactor-record, include=FALSE-------------------------------------------
remember_model("bifactor-specification", bifactor_paths, "none", input = "unfitted parameter-table specification")

## ----evaluated-examples, echo=FALSE-------------------------------------------
knitr::kable(data.frame(Example = names(.models),
  Input = vapply(.models, `[[`, character(1), "input"),
  Labels = vapply(.models, `[[`, character(1), "label")), row.names = FALSE)

