---
title: "Plot composer"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Plot composer}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(ggalign)
```

# align_plots
Special thanks to the `patchwork` project—many core codes of the plot composer
process were adapted from `patchwork`. We have added new features to better
implement `ggalign`'s layout functions (`ggheatmap()` and `ggstack()`),
including: 

  - `free_align()`
  - `free_border()`
  - `free_guide()`
  - `free_lab()`
  - `free_space()`
  - `free_vp()`

These features have not been pushed to `patchwork` because they required
significant modification of core code. We attempted to merge them, but the
author of `patchwork` decided to implement some of these features independently.
The latest version of patchwork now includes `free_align()`, `free_lab()`, and
`free_space()` functionality under a single function: `patchwork::free()`. For
more details, see: <https://www.tidyverse.org/blog/2024/09/patchwork-1-3-0/>.

The plot composer function in `ggalign` is `align_plots()`, which behaves
similarly to `cowplot::align_plots()` and `patchwork::wrap_plots()`. However,
you can directly use `align_plots()` with `ggheatmap()` and `ggstack()`,
ensuring that they align correctly by plot panel. Additionally, `align_plots()`
can align `pheatmap` and `ComplexHeatmap` objects, although they won't align by
panel area with ggplot2. 

## Plot Assembly
We'll start with a few well-known example plots:
```{r}
p1 <- ggplot(mtcars) +
  geom_point(aes(mpg, disp))
p2 <- ggplot(mtcars) +
  geom_boxplot(aes(gear, disp, group = gear))
p3 <- ggplot(mtcars) +
  geom_bar(aes(gear)) +
  facet_wrap(~cyl)
p4 <- ggplot(mtcars) +
  geom_bar(aes(carb))
p5 <- ggplot(mtcars) +
  geom_violin(aes(cyl, mpg, group = cyl))
```

Either add the plots as single arguments
```{r}
align_plots(p1, p2, p3, p4, p5)
```

Or use bang-bang-bang to add a list of plots
```{r}
align_plots(!!!list(p1, p2, p3), p4, p5)
```

## Empty area
You can use `NULL` to indicate the empty area.
```{r}
align_plots(p1, NULL, p2, NULL, p3, NULL)
```

## Controlling the grid
Like `patchwork`, if no specific layout is provided, `align_plots()` will
attempt to create a grid that is as square as possible, with each column and row
taking up equal space: 
```{r}
align_plots(p1, p2, p3, p4, ncol = 3)
```

To adjust the widths of columns, use:
```{r}
align_plots(p1, p2, p3, p4, widths = c(2, 1))
```

## Guide legends
By default, `align_plots()` won't collect any guide legends. You can use the
`guides` argument to control which side of the guide legends should be
collected. They will be collected to their original side. Here, we use
`patch_titles()` to indicate the guide legend position (instead of using
`ggtitle()`). `patch_titles()` can add titles on four sides, and the title will
be placed between the plot panel and the guide legend.

```{r}
p_right <- ggplot(mtcars) +
  geom_point(aes(hp, wt, colour = mpg)) +
  patch_titles("right") +
  labs(color = "right")
p_top <- p_right +
  patch_titles("top") +
  scale_color_continuous(
    name = "top",
    guide = guide_colorbar(position = "top")
  )
p_left <- p_right +
  patch_titles("left") +
  scale_color_continuous(
    name = "left",
    guide = guide_colorbar(position = "left")
  )
p_bottom <- p_right +
  patch_titles("bottom") +
  scale_color_continuous(
    name = "bottom",
    guide = guide_colorbar(position = "bottom")
  )
align_plots(p_right, p_bottom, p_top, p_left, guides = "tlbr")
```

If `align_plots()` is nested in another `align_plots()`, the nested
`align_plots()` will inherit the `guides` argument from the upper-level
`align_plots()`. And the top-level `align_plots()` won't collect guide legends
from plots within the nested `align_plots()` unless the nested `align_plots()`
collects them first.

## free_guide
The `free_guide()` function allows you to override the `guides` argument for a
single plot.
```{r}
align_plots(
  free_guide(p_right, NULL),
  free_guide(p_bottom, NULL),
  free_guide(p_top, NULL),
  free_guide(p_left, NULL),
  guides = "tlbr"
)
```

You can also specify which guide positions to be collected for individual plots.
```{r}
align_plots(
  free_guide(p_right, "r"),
  free_guide(p_bottom, "b"),
  free_guide(p_top, "t"),
  free_guide(p_left, "l")
)
```

## Session information
```{r}
sessionInfo()
```
