---
title: "Getting started with depictr"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting started with depictr}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
bibliography: ../inst/REFERENCES.bib
csl: apa.csl
link-citations: true
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(collapse = FALSE, comment = "",
                      fig.width = 7, fig.height = 4.5, dpi = 96,
                      dev.args = list(bg = "transparent"))
# Console colour carries no meaning on a rendered page. pkgdown turns it on for
# its own build, and the escape sequences then reach the reader as literal text,
# so colour is switched off here for a plain vignette render and a site build
# alike. The fixed width keeps printed output inside the documentation column.
options(cli.num_colors = 1, cli.hyperlink = FALSE, crayon.enabled = FALSE,
        width = 80)

# Figures on the package website sit on a warm off-white page in light mode and
# are inverted by pkgdown in dark mode, so an opaque background would read as a
# pale slab one way and a black plate the other. Two layers paint that
# background, and both have to go. The device canvas is made transparent by
# `dev.args` above, and theme_depictr() then inherits theme_minimal()'s white
# plot.background, which is drawn over that canvas, so it is cleared as each
# figure is printed. This is deliberately a vignette-level choice: theme_depictr()
# keeps its opaque background, which is what a figure saved for a paper wants.
transparent_bg <- ggplot2::theme(
  plot.background  = ggplot2::element_rect(fill = NA, colour = NA),
  panel.background = ggplot2::element_rect(fill = NA, colour = NA)
)
knit_print.ggplot <- function(x, ...) knitr::normal_print(x + transparent_bg)
knit_print.patchwork <- function(x, ...) knitr::normal_print(x & transparent_bg)

```

depictr is a single, consistent toolkit of plots that span the whole
analysis workflow, from a first look at the data, through model estimates and
predictions, to diagnostics, uncertainty and reporting. Every plotting function
returns a `ggplot2` object [@wickham2016] (or a `patchwork` for composite
panels), so you can keep customising with the usual `+` syntax, and every plot
shares one theme, one palette and one set of label conventions.

```{r}
library(depictr)
```

## Five datasets to explore

The package ships with five reproducibly simulated datasets, each chosen to
exercise a different family of plots. They are documented under their names
(e.g. `?lexical_decision`) and load with `data()`:

* `lexical_decision`: a counterbalanced, crossed reaction-time/accuracy
  experiment (participant, item, condition, modality, word frequency). For
  mixed models and the classification plots.
* `wellbeing_survey`: a cross-sectional survey (life satisfaction, stress,
  sleep, income, age, ordered education, region) with *informative*
  missingness. For descriptives, correlations, regression and missing data.
* `crop_yield`: a field trial with a genuine fertiliser-by-treatment
  interaction. For regression, scatter-trend and interaction plots.
* `clinical_trial`: a two-arm trial with separating survival curves and a
  rare adverse-event outcome. For survival and imbalanced classification.
* `monthly_sales`: two seasonal monthly series (indoor/outdoor). For the
  time-series plots.

## A tour by task

Begin with the data. `explore_bivariate()` chooses a suitable plot for any pair
of variables, here a scatter with a trend because both are numeric.

```{r}
explore_bivariate(crop_yield, fertiliser, yield)
```

Turn next to the model. After fitting it, `coefficient_plot()` draws a forest
plot of the estimates.

```{r}
fit <- lm(yield ~ rainfall + fertiliser + soil_ph + treatment,
          data = crop_yield)
coefficient_plot(fit, order = "descending", title = "Drivers of crop yield")
```

To see what the model implies, `effects_plot()` traces the predicted response as
one predictor varies.

```{r}
effects_plot(fit, "fertiliser")
```

`residual_diagnostics_plot()` gathers the usual checks of the fit into one
panel.

```{r, fig.height = 6}
residual_diagnostics_plot(fit)
```

For uncertainty, `posterior_plot()` summarises posterior or simulation draws as
a distribution per parameter. These are the fixed-effect posterior draws from a
Bayesian fit of the lexical-decision model, shipped with the package.

```{r}
draws <- readRDS(system.file("extdata", "lexdec_draws.rds",
                             package = "depictr"))
posterior_plot(draws[c("conditionunrelated", "modalityauditory",
                       "word_frequency")],
               labels = c(conditionunrelated = "condition",
                          modalityauditory = "modality",
                          word_frequency = "word frequency"),
               title = "Lexical-decision fixed effects (ms)")
```

## The shared spine: `tidy_estimates()`

Most of the model functions rest on `tidy_estimates()`, which turns a model, or
a data frame of pre-computed estimates, into one standard table. Because the
plotting functions also accept that table, estimates from any source (Bayesian
posteriors, bootstrap intervals, or figures taken from a paper) can be supplied
directly.

```{r}
tidy_estimates(fit)
```

## A consistent, accessible look

`theme_depictr()`, `depictr_palette()` and `scale_colour_depictr()` style your
own plots too:

```{r}
library(ggplot2)
ggplot(crop_yield, aes(fertiliser, yield, colour = treatment)) +
  geom_point(alpha = 0.7) +
  scale_colour_depictr() +
  theme_depictr()
```

`depictr_palette()` returns the underlying hex colours directly, ready to feed
`scale_fill_manual()` or a base-graphics `col =` argument:

```{r}
depictr_palette(4)
```

The qualitative palette is based on the Okabe-Ito set [@okabe2008], which stays
distinguishable under the common forms of colour-vision deficiency, and
sequential and diverging variants are available too. Preview them with:

```{r, fig.height = 5}
palette_preview(type = "all")
```

`palette_preview()` can also *simulate* a colour-vision deficiency, so you can
check a palette as a deuteranope (red-green) would see it:

```{r, fig.height = 2.6}
palette_preview(cvd = "deutan")
```

The simulation is available on its own as `simulate_cvd()`, and `palette_safety()`
turns it into a verdict: for normal vision and each deficiency at full severity it
reports the smallest perceptual distance between any two colours in a palette, so
the accessibility claim comes with a number attached.

```{r}
palette_safety()
```

## Auditing the figure you are about to submit

A safe palette is not a safe figure. Once a plot has been extended with your own
scale, shrunk to fit a journal column, or asked to distinguish groups by colour
alone, the palette's guarantee no longer describes what a reader will see.
`check_figure()` reads a built plot and reports what it measured, next to the
threshold it was measured against, so each verdict can be argued with.

```{r}
grouped <- ggplot(crop_yield, aes(fertiliser, yield, colour = treatment)) +
  geom_point(alpha = 0.7) +
  scale_colour_depictr() +
  theme_depictr()

check_figure(grouped)
```

Two rows are worth dwelling on. `geometry_contrast` measures each encoding colour
against the panel background, and the palette's orange sits at 2.25 against white,
below the 3:1 that WCAG asks of a graphical object [@wcag22]. `redundant_encoding`
is zero because nothing but colour tells the two treatments apart. Mapping shape
as well, and letting the darker vermillion do the second colour's work, clears
both:

```{r}
mended <- ggplot(crop_yield, aes(fertiliser, yield, colour = treatment,
                                 shape = treatment)) +
  geom_point(alpha = 0.7) +
  scale_colour_manual(values = c("#005b96", "#d55e00")) +
  theme_depictr()

check_figure(mended)[, c("check", "measured", "threshold", "verdict")]
```

The audit also takes a stated output width, which is where most figure text
quietly fails. Text is drawn in points, so a figure saved seven inches wide and
then printed in an 8.9 cm column arrives at half the size it looked on screen:

```{r}
subset(check_figure(grouped, width_cm = 8.9), check == "text_size")
```

One limitation belongs here, beside the claim it qualifies, since the package is
the one making that claim. The eight-colour qualitative palette clears every
colour-vision check and fails the greyscale check: its orange and its sky blue
differ by 0.79 in CIE lightness, so a black-and-white printer renders them as the
same grey. The Okabe-Ito guarantee is about hue confusion and was never a claim
about greyscale. The threshold stays where it is, the check reports the number,
and the claim has been narrowed to match. A figure that may be printed in black
and white wants fewer groups, a sequential palette, or a redundant shape or line
type.

```{r}
eight <- data.frame(g = factor(letters[1:8]), x = 1:8, y = 1:8)
p8 <- ggplot(eight, aes(x, y, colour = g)) +
  geom_point() +
  scale_colour_depictr() +
  theme_depictr()

subset(check_figure(p8), check == "greyscale_separability")
```

Set the look once for a whole script with `depictr_options()`. It carries the
base size and family, the brand and accent colours and a custom palette, so the
same arguments need not travel with every call. Called with no arguments it
reports the current settings:

```{r}
depictr_options()
```

Supplying arguments sets them for every later plot and returns the previous
values, so you can put the look back afterwards:

```{r, fig.height = 4}
old <- depictr_options(base_size = 13, accent = "#b3589a")
coefficient_plot(fit, title = "Set once, applied everywhere")
do.call(depictr_options, old)   # restore the previous settings
```

## Where to next

The remaining articles go into each area in turn.
`vignette("exploring-data")` covers distributions, categories, bivariate plots,
scatter-plot matrices, correlations, missingness, outliers, summary tables and
the estimation plots.
`vignette("model-estimates")` is the flagship: forest plots, model comparison,
predicted values, interactions, random effects, optimiser checks and the
frequentist-over-Bayesian-posterior overlay.
`vignette("diagnostics-and-uncertainty")` covers residuals, GLM-appropriate
binned residuals, the classification suite (ROC, PR, gains, lift, calibration,
thresholds) on an imbalanced outcome, and power curves.
Two further articles, `vignette("multivariate-and-survival")` and
`vignette("time-series")`, cover the remaining methods.

## References
