--- title: "Plot options" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Plot options} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, comment = "#>" ) ``` Plot options control the actions of plots within the layout. These options can be applied either globally to all plots in the layout or individually to specific plots. - To apply a plot option to a single plot, use the `+` operator. - To set a plot option at the layout level (affecting all plots), use the `-` operator. >Plot options inherit properties from parent layout options hierarchically. The package currently provides three plot options, each prefixed with `plot_`: - `plot_theme`: Sets the default theme for the plot. - `plot_data`: Transforms the plot data. Many functions in this package require a specific data format to align observations, `plot_data()` helps reformat data frames as needed. - `plot_align`: Defines alignment specifications for plots within the layout. ```{r setup} library(ggalign) ``` ```{r setup_data} set.seed(123) small_mat <- matrix(rnorm(81), nrow = 9) rownames(small_mat) <- paste0("row", seq_len(nrow(small_mat))) colnames(small_mat) <- paste0("column", seq_len(ncol(small_mat))) ``` # `plot_theme` The `plot_theme()` function extends `theme()` to set a default theme for plots, allowing you to input `theme()` elements directly or modify the theme elements. To set a plot option for a single plot, simply use the `+` operator: ```{r} ggheatmap(small_mat) + # change the default theme of the heatmap body plot_theme(plot.background = element_rect(fill = "red")) ``` Using a `theme()` Object in `plot_theme()`. ```{r} ggheatmap(small_mat, filling = FALSE) + geom_tile(aes(fill = value), width = 0.9, height = 0.9) + # change the default theme of the heatmap body plot_theme(theme_bw(), plot.background = element_rect(fill = "red")) ``` Note that `plot_theme()` serves as the default theme and will always be overridden by any `theme()` settings applied directly to the plot. The default theme (`plot_theme()`) is applied first, followed by any specific `theme()` settings, even if `theme()` is added before `plot_theme()`. ```{r} ggheatmap(small_mat) + # change the plot theme of the heatmap body theme(plot.background = element_rect(fill = "blue")) + # change the default theme of the heatmap body plot_theme(plot.background = element_rect(fill = "red")) ``` By using the `-` operator with plot options, we apply the option directly to the active layout. ```{r} ggheatmap(small_mat) + # Change the active layout to the top annotation anno_top() + # add a dendrogram to the top annotation align_dendro() + # add a bar plot to the top annotation ggalign(aes(.names, value, fill = factor(.names)), data = rowSums) + geom_bar(stat = "identity") - # Change the default theme of the top annotation # All plots in the top annotation will inherit this default theme plot_theme(plot.background = element_rect(fill = "red")) ``` Unlike individual ggplot2 elements added to each plot, layout-level options set by `-` operator are inherited by all plots in the layout when rendered. Any plot-specific options will override these layout-level options, regardless of the order in which they are added. ```{r} ggheatmap(small_mat) + # Change the active layout to the top annotation anno_top() + # add a dendrogram to the top annotation align_dendro() + # change the plot_theme for the dendrogram plot plot_theme(plot.background = element_rect(fill = "blue")) + # add a bar plot to the top annotation ggalign(aes(.names, value, fill = factor(.names)), data = rowSums) + geom_bar(stat = "identity") - # Change the default theme of the top annotation # All plots in the top annotation will inherit this default theme # But the plot-specific options will override these plot_theme(plot.background = element_rect(fill = "red")) ``` # `plot_data` `align_gg()`/`ggalign()` requires the specific data format for its operations. If you need to transform or filter data for individual `geoms`, you can use the `data` argument within each `geom`. However, if you have multiple `geoms` and want a consistent transformation applied across all, you can utilize the `plot_data()` function. This allows you to transform the default data for the entire plot. The `plot_data()` accepts a function that takes a data frame as input and returns a modified data frame. By default, `plot_data()` will attempt to inherit from the parent layout if the data is inherited from it. However, there is one exception: `align_dendro()` will not inherit `plot_data()` transformations by default. ```{r} set.seed(1234L) ggheatmap(small_mat) + anno_top() + align_kmeans(3L) + # we add a bar plot ggalign() + # we subest the plot data plot_data(~ subset(.x, .panel == 1L)) + geom_bar(aes(y = value, fill = .row_names), stat = "identity") ``` # `plot_align` The `plot_align()` function defines the align Specifications for plots. ## guides By default, `ggheatmap()` will collect all guide legends on the side from which they originate. ```{r fig.dim = c(12, 12)} heatmap_collect_all_guides <- ggheatmap(small_mat, width = 2, height = 2L) + scale_fill_viridis_c(name = "I'm from heatmap body") + theme(axis.text.x = element_text(angle = -60, hjust = 0)) + anno_top() + align_dendro(aes(color = branch), k = 3L) + scale_color_brewer( name = "I'm from top annotation", palette = "Dark2", guide = guide_legend(position = "right") ) + anno_left() + align_dendro(aes(color = branch), k = 3L) + scale_color_brewer( name = "I'm from left annotation", palette = "Dark2", guide = guide_legend(position = "top", direction = "vertical") ) + anno_bottom() + align_dendro(aes(color = branch), k = 3L) + scale_color_brewer( name = "I'm from bottom annotation", palette = "Dark2", guide = guide_legend(position = "left") ) + anno_right() + align_dendro(aes(color = branch), k = 3L) + scale_color_brewer( name = "I'm from right annotation", palette = "Dark2", guide = guide_legend(position = "bottom", direction = "vertical") ) & theme(plot.margin = margin()) heatmap_collect_all_guides ``` Use the `guides` argument control which side of guide legends should be gathered. In the following example, we'll collect the guide legends only on the `top` and `bottom` sides: ```{r fig.dim = c(12, 12)} heatmap_collect_all_guides + # reset the active context to the heatmap layout quad_active() - # we set global `guides` argument for the heatmap layout # we only collect guides in the top and bottom side plot_align(guides = "tb") ``` You can also apply the `plot_align()` function directly to specific plots: ```{r fig.dim = c(12, 12)} heatmap_collect_all_guides + # reset the active context to the heatmap layout quad_active() - # we set global `guides` argument for the heatmap layout # we only collect guides in the top and bottom side plot_align(guides = "tb") + # `+` apply it to the current active plot # for the heatmap body, we collect guide in the right side plot_align(guides = "r") ``` The guide legends within the annotation stack are first collected by the `stack_layout()` itself and then passed to the overall heatmap layout for further integration. By default, it inherits the `guides` arguments from the heatmap layout. See following example: ```{r fig.dim = c(12, 12)} heatmap_collect_all_guides + # reset the active context to the heatmap layout quad_active() - # we set global `guides` argument for the heatmap layout # we only collect guides in the top and bottom side plot_align(guides = "tb") + # we ensure the active context is in the bottom annotation # By default, it inherits "guides" argument from the heamtap layout, which # means it'll collect "guides" in the top and bottom side anno_bottom() + # for the dendrogram in the bottom annotation, we collect guide in the left side plot_align(guides = "l") ``` Here, the guide legend is collected by the bottom annotation but will not be collected by the heatmap layout since the heatmap layout only gathers guides from the `top` and `bottom`. In this way, the guide legends of the annotation stack will be put around the annotation stack layout. To override this guide collection behavior for the heatmap annotation, you can use the `free_guides` argument of the `quad_anno()`/`anno_*()` function. This differs from the `guides` argument in `plot_align()`, which controls the behavior for the plots in the layout. The `free_guides` argument specifies which guide legends from the annotation stack layout should be collected by the heatmap layout. ```{r fig.dim = c(12, 12)} heatmap_collect_all_guides + # reset the active context to the heatmap layout quad_active() - # we set global `guides` argument for the heatmap layout # we only collect guides in the top and bottom side plot_align(guides = "tb") + # we also collect guides in the left side for the bottom annotation stack # layout in the heatmap layout anno_bottom(free_guides = "l") + # for the dendrogram in the bottom annotation, we collect guide in the left side plot_align(guides = "l") ``` >Note: The heatmap layout will only collect guide legends from the annotation stack if the stack layout collects its own guides first. ## free_spaces By default, `ggheatmap()` will align all elements of the plot, which can sometimes lead to unwanted spacing. Consider the following example: ```{r} ggheatmap(small_mat) + scale_fill_viridis_c() + anno_top(size = unit(30, "mm")) + align_dendro() + scale_y_continuous( expand = expansion(), labels = ~ paste("very very long labels", .x) ) + anno_left(unit(20, "mm")) + align_dendro() ``` In this case, the left annotation stack is positioned far from the heatmap body due to the wide axis labels in the top annotation stack. This occurs because the top annotation stack is aligned with the heatmap body. To fix this, you can remove the left borders around the panel of the top annotation stack by setting `free_spaces = "l"`. ```{r} ggheatmap(small_mat) + scale_fill_viridis_c() + anno_top(size = unit(30, "mm")) - plot_align(free_spaces = "l") + align_dendro() + scale_y_continuous( expand = expansion(), labels = ~ paste("very long labels", .x) ) + anno_left(unit(20, "mm")) + align_dendro() ``` One useful way to utilize `free_spaces` is to position the guide legends next to the annotations. (Note the guide legend from the bottom annotation): ```{r fig.dim = c(12, 12)} heatmap_collect_all_guides + # we only collect guides in the top and bottom side quad_active() - plot_align(guides = "tb") + # 1. in the bottom annotation stack layout, we collect the legends in the # left side # 2. we remove the spaces of the left border in the annotation anno_bottom() - plot_align(guides = "l", free_spaces = "l") ``` In `ggheatmap()`/`quad_layout()`, the behavior of the `free_spaces` and `free_labs` arguments differs from `guides` arguments in `plot_align()` when inheriting from the parent layout: - For `top` and `bottom` annotations, it inherits from the left ("l") and right ("r") axes. - For `left` and `right` annotations, it inherits from the top ("t") and bottom ("b") axes. ## free_labs By default, we won't align the axis titles. ```{r} ggheatmap(small_mat) + scale_fill_viridis_c() + ylab("Heatmap title") + anno_top(size = unit(30, "mm")) + align_dendro() + ylab("Annotation title") ``` To align axis titles, you can set `free_labs = NULL`. Alternatively, A single string containing one or more of axis positions ("t", "l", "b", "r") to indicate which axis titles should be free from alignment. ```{r} ggheatmap(small_mat) - plot_align(free_labs = NULL) + scale_fill_viridis_c() + ylab("Heatmap title") + anno_top(size = unit(30, "mm")) + align_dendro() + ylab("Annotation title") ``` ## Session information ```{r} sessionInfo() ```