---
title: "Getting Started with umx"
subtitle: "Your first structural equation model using umxRAM() and umxSummary()"
author: "Timothy C. Bates"
date: "`r Sys.Date()`"
output:
  rmarkdown::html_vignette:
    toc: true
vignette: >
  %\VignetteIndexEntry{Getting Started with umx}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---


```{r setup, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 6,
  fig.height = 5
)
library(umx)
# Never auto-open browser plots during package check
umx_set_auto_plot(FALSE)
```


## Introduction

`umx` is a package that makes building, running, and reporting Structural Equation Models (SEM) fast, efficient, and readable in R.

This vignette shows a new user how to:

1. Load classic data (Holzinger & Swineford, 1939)
2. Build a simple one-factor model using `umxRAM()`
3. View and interpret results using `umxSummary()`
4. Save a path diagram as a **PNG** (safe for non-interactive builds)

Ordinal / WLS workflows are covered in `vignette("WLS_in_umx")`.

## The Holzinger and Swineford (1939) data

This well-known dataset contains scores on nine cognitive tests for 301 school children. The variables `x1` to `x9` measure different aspects of cognitive ability.

Because `umx` imports `OpenMx`, the data is easy to load:

```{r load-data}
# Load the classic Holzinger Swineford 1939 data (x1:x9)
data("HS.ability.data")

# Define the manifest (observed) variables
manifests = c("visual","cubes","flags","paragrap","sentence","wordm","addition","counting","straight")
# Quick look at the correlations
umx_cor(HS.ability.data[, manifests])
```
## Build a one-factor model with `umxRAM()`

`umxRAM()` lets you describe models using simple `umxPath()` statements. Any variable name not in the data is treated as a latent variable.

Here we build a model in which a single latent factor `g` (general ability) accounts for the covariances among the manifests.

```{r build-model, results = "hide", message = FALSE}
m1 = umxRAM("Holzinger_one_factor", data = HS.ability.data,
  # Factor loadings (G predicts each x)
  umxPath("g", to = manifests),
  # Residual means and variances for the observed variables
  umxPath(v.m. = manifests),
  # Fix the latent factor variance to 1 (for identification)
  umxPath(v1m0 = "g")
)
```

That's it — `umxRAM()` automatically:

- Detects manifests vs latents
- Adds starting values
- Runs the model
- Produces an initial summary

## View results with `umxSummary()`

`umxSummary()` gives clean output. Tip: `report = "html"` gives a publication-ready table.

```{r summary-basic}
umxSummary(m1)
```

### Standardized solution

Add `std = TRUE` to see standardized estimates (useful for interpretation):

```{r summary-std}
umxSummary(m1, std = TRUE)
```

The output includes:

- A table of standardized loadings, variances, and means
- Model fit information ($\chi^2$, CFI, TLI, RMSEA)
- Helpful warnings when fit is poor

> Note: A single-factor model is a poor fit to these data (as expected — the data were designed to measure three correlated abilities). This is intentional for demonstration: you can immediately see how `umxSummary()` highlights areas for model improvement.

## Alternative: lavaan-style syntax

`umxRAM()` also accepts lavaan model syntax directly:

```{r lavaan-string, results = "hide", message = FALSE}
m2 = umxRAM(paste("g =~", paste(manifests, collapse = " + ")),
  data = HS.ability.data)
```

```{r lavaan-summary}
umxSummary(m2, std = TRUE)
```

This is handy when you have a lavaan model string from elsewhere.

## Path diagram as PNG

Interactive browser plots (DiagrammeR widgets) can hang or stall non-interactive package checks. For vignettes and scripts, write a **PNG** via graphviz → SVG → PNG, then include it. Requires Suggested packages `DiagrammeR`, `DiagrammeRsvg`, and `rsvg`.

```{r plot-png, fig.cap = "Standardized one-factor Holzinger model (PNG)", message = FALSE}
# Prefer a stored PNG under vignettes/figures/ (no browser). Regenerate if missing.
figDir = "figures"
dir.create(figDir, showWarnings = FALSE)
gvPath = file.path(figDir, "holzinger_one_factor.gv")
pngPath = file.path(figDir, "holzinger_one_factor.png")
if (!file.exists(pngPath)) {
	# digraph only; capture.output silences plot()'s cat() of the graph
	dot = NULL
	utils::capture.output({
		dot <<- plot(m1, std = TRUE, means = FALSE, file = NA)
	})
	cat(dot, file = gvPath)
	# 1) Graphviz CLI
	dotBin = Sys.which("dot")
	if (nzchar(dotBin)) {
		system2(dotBin, c("-Tpng", "-o", pngPath, gvPath), stdout = FALSE, stderr = FALSE)
	}
	# 2) DiagrammeR → SVG → PNG (Suggests: DiagrammeRsvg, rsvg)
	if (!file.exists(pngPath) &&
		requireNamespace("DiagrammeR", quietly = TRUE) &&
		requireNamespace("DiagrammeRsvg", quietly = TRUE) &&
		requireNamespace("rsvg", quietly = TRUE)) {
		svgTxt = DiagrammeRsvg::export_svg(DiagrammeR::grViz(dot))
		rsvg::rsvg_png(charToRaw(svgTxt), pngPath)
	}
}
if (file.exists(pngPath)) {
	knitr::include_graphics(pngPath)
} else {
	message(
		"PNG plot unavailable (install graphviz `dot`, or DiagrammeR + DiagrammeRsvg + rsvg). ",
		"Ship/regenerate ", pngPath, " under vignettes/figures/."
	)
}
```

We can also get robust measures of fit and uncertainty using `uncertainty = "MLR"`.
These use sandwich-based scaling + Brosseau-Liard & Savalei (2012) adjustments to CFI/TLI/RMSEA:

```{r uncertainty, message = FALSE}
umxSummary(m1, std = TRUE, uncertainty = "MLR", refModels = FALSE)
```

## Ordinal and WLS models

For ordered factors, DWLS/WLS, and Satorra–Bentler nested tests, see:

```r
vignette("WLS_in_umx", package = "umx")
```

## Next steps

- Learn more about path specification: `?umxPath`
- See all the options for `umxRAM()`: `?umxRAM`
- Control output format: `?umxSummary`
- Compare models: `?umxCompare`
- Uncertainty (SEs, robust SEs, profile CIs): `vignette("SEs_robustSEs_and_ProfileCIs", package = "umx")`
- For twin models see the twin modeling functions (`umxACE()`, etc.)

Welcome to `umx`!

## References

Holzinger, K. J., & Swineford, F. (1939). A study in factor analysis: The stability of a bi-factor solution. *Supplementary Educational Monographs*, 48. University of Chicago Press.
