---
title: "Arranging brain views"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Arranging brain views}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r}
#| label: setup
#| include: false
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  fig.width = 7,
  fig.height = 5
)
```

```{r}
#| label: load-packages
library(ggseg)
library(ggplot2)
```

A brain atlas typically has several views -- lateral and medial for cortical
atlases, or axial, coronal, and sagittal slices for subcortical and tract
atlases. `position_brain()` controls how those views are arranged in
the final plot.

The function works differently depending on the atlas type, so this vignette
covers cortical and subcortical/tract atlases separately.

## Cortical atlases

Cortical atlases like `dk` have two layout dimensions: **hemi** (left or
right) and **view** (lateral, medial, etc.). The formula syntax mirrors
`facet_grid()` -- left side is rows, right side is columns:

```{r}
#| label: fig-hemi-by-view
#| fig-cap: "Cortical atlas with hemispheres as rows and views as columns."
ggplot() +
  geom_brain(
    atlas = dk(),
    position = position_brain(hemi ~ view),
    show.legend = FALSE
  ) +
  theme_void()
```

Flip the formula to transpose the layout:

```{r}
#| label: fig-view-by-hemi
#| fig-cap: "Transposed layout with views as rows and hemispheres as columns."
ggplot() +
  geom_brain(
    atlas = dk(),
    position = position_brain(view ~ hemi),
    show.legend = FALSE
  ) +
  theme_void()
```

### Stacking all views

Use `.` with `+` to collapse everything into a single row or column. This
is handy for compact figures:

```{r}
#| label: fig-single-row
#| fig-cap: "All brain views stacked in a single row."
ggplot() +
  geom_brain(
    atlas = dk(),
    position = position_brain(. ~ hemi + view),
    show.legend = FALSE
  ) +
  theme_void()
```

```{r}
#| label: fig-single-column
#| fig-cap: "All brain views stacked in a single column."
ggplot() +
  geom_brain(
    atlas = dk(),
    position = position_brain(hemi + view ~ .),
    show.legend = FALSE
  ) +
  theme_void()
```

## Subcortical and tract atlases

Subcortical atlases like `aseg` and tract atlases like `tracula` don't have
the hemisphere/view pairing that cortical atlases do. Their views are
individual slices (e.g. `"axial_3"`, `"sagittal"`). That opens up a
different set of positioning tools.

### Horizontal and vertical

The simplest options. `"horizontal"` is the default:

```{r}
#| label: fig-aseg-horizontal
#| fig-cap: "Subcortical atlas views arranged horizontally."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain("horizontal"),
    show.legend = FALSE
  ) +
  theme_void()
```

```{r}
#| label: fig-aseg-vertical
#| fig-cap: "Subcortical atlas views arranged vertically."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain("vertical"),
    show.legend = FALSE
  ) +
  theme_void()
```

### Grid layouts

When you have many views, a grid keeps things readable. Specify `nrow`,
`ncol`, or both:

```{r}
#| label: fig-aseg-nrow
#| fig-cap: "Subcortical atlas views in a two-row grid."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(nrow = 2),
    show.legend = FALSE
  ) +
  theme_void()
```

```{r}
#| label: fig-aseg-ncol
#| fig-cap: "Subcortical atlas views in a three-column grid."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(ncol = 3),
    show.legend = FALSE
  ) +
  theme_void()
```

### Picking specific views

The `views` parameter lets you select which views to include and in what
order. Check what's available with `ggseg.formats::atlas_views()`:

```{r}
#| label: aseg-views
ggseg.formats::atlas_views(aseg())
```

```{r}
#| label: fig-aseg-select-views
#| fig-cap: "A subset of subcortical views selected by name."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(
      views = c("sagittal", "axial_3", "coronal_3")
    ),
    show.legend = FALSE
  ) +
  theme_void()
```

Combine `views` with `nrow` or `ncol` for a custom grid:

```{r}
#| label: fig-aseg-custom-grid
#| fig-cap: "Custom two-row grid with selected subcortical views."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(
      views = c("sagittal", "axial_3", "axial_5", "coronal_3"),
      nrow = 2
    ),
    show.legend = FALSE
  ) +
  theme_void()
```

### Grouping by slice type

The `type ~ .` formula groups views by their orientation -- all axial slices
together, all coronal slices together, and so on. The type is extracted from
the view name (everything before the first underscore):

```{r}
#| label: aseg-type-group
#| eval: false
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(type ~ .),
    show.legend = FALSE
  ) +
  theme_void()
```

## Adding view labels

Use `annotate_brain()` to label each view with its name. For cortical
atlases the label combines hemisphere and view (e.g. "left lateral"); for
subcortical and tract atlases it uses the view name directly.

Store the `position_brain()` specification in an object so both layers
share the same layout:

```{r}
#| label: fig-dk-view-labels
#| fig-cap: "Cortical atlas with view labels."
pos <- position_brain(hemi ~ view)
ggplot() +
  geom_brain(atlas = dk(), position = pos, show.legend = FALSE) +
  annotate_brain(atlas = dk(), position = pos) +
  theme_void()
```

It works with any positioning — horizontal, vertical, grid, and formula
layouts:

```{r}
#| label: fig-aseg-view-labels
#| fig-cap: "Subcortical atlas with view labels in a two-row grid."
pos <- position_brain(nrow = 2)
ggplot() +
  geom_brain(atlas = aseg(), position = pos, show.legend = FALSE) +
  annotate_brain(atlas = aseg(), position = pos) +
  theme_void()
```

Labels sit a little above each view by default (`padding = 0.05`). Increase
`padding` to push them further out, and tune the text through standard
`annotate()` arguments:

```{r}
#| label: fig-styled-labels
#| fig-cap: "View labels with extra padding and custom styling."
ggplot() +
  geom_brain(atlas = dk(), show.legend = FALSE) +
  annotate_brain(
    atlas = dk(),
    padding = 0.08,
    size = 2.5,
    colour = "grey50",
    fontface = "italic"
  ) +
  theme_void()
```

## Zooming in on regions of interest

For "focus" atlases -- where only a few structures carry labels and the rest
of the brain is grey context -- `position_brain(zoom = ...)` crops
each view onto the regions of interest, so they fill the panel while the
surrounding context becomes a tidy grey frame. Every view keeps the same
allotted cell.

### Focus on the regions in your data

`zoom = TRUE` focuses on whatever regions your data supplies values for (or,
with no data, the atlas's labelled regions):

```{r}
#| label: fig-zoom-data
#| fig-cap: "Each view zoomed onto the regions present in the supplied data."
my_data <- data.frame(
  region = ggseg.formats::atlas_regions(aseg())[1:3],
  value = c(1, 2, 3)
)

ggplot() +
  geom_brain(
    atlas = aseg(),
    data = my_data,
    aes(fill = value),
    position = position_brain(zoom = TRUE)
  ) +
  scale_fill_viridis_c(na.value = "grey85") +
  theme_void()
```

### Name the focus regions explicitly

Pass a character vector to choose exactly which regions each view zooms onto,
independent of any data you plot:

```{r}
#| label: fig-zoom-explicit
#| fig-cap: "Zoom targeted at a named set of regions."
focus <- c("Thalamus Proper", "Putamen", "Hippocampus")

ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(zoom = focus),
    show.legend = FALSE
  ) +
  theme_void()
```

### Control the margin with `zoom_pad`

`zoom_pad` sets how much breathing room to leave around the focus regions, as
a fraction of their size (5% by default). A smaller value crops tighter; a
larger value keeps more context in frame:

```{r}
#| label: fig-zoom-tight
#| fig-cap: "A tighter crop using a small zoom_pad."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(zoom = focus, zoom_pad = 0.01),
    show.legend = FALSE
  ) +
  theme_void()
```

```{r}
#| label: fig-zoom-loose
#| fig-cap: "More surrounding context using a larger zoom_pad."
ggplot() +
  geom_brain(
    atlas = aseg(),
    position = position_brain(zoom = focus, zoom_pad = 0.25),
    show.legend = FALSE
  ) +
  theme_void()
```

## Dropping the grey context

Set `context = FALSE` to remove the unlabelled context regions entirely. The
remaining atlas regions are re-gathered into a tighter layout:

```{r}
#| label: fig-no-context
#| fig-cap: "Subcortical atlas with the grey context regions removed."
ggplot() +
  geom_brain(atlas = aseg(), context = FALSE, show.legend = FALSE) +
  theme_void()
```

## The sf workflow

If you work with brain atlases as sf objects -- for example to layer
`geom_sf()` text labels -- `reposition_brain()` rearranges the sf data using
the same arguments shown here. See `vignette("geom-sf")` for that workflow.
