ggplots
and other
grid
-based Bioconductor visualizationsvignettes/guides/incorporating_ggplots.Rmd
incorporating_ggplots.Rmd
In addition to its numerous built-in genomic functions,
plotgardener
can size and place ggplots
and
other grid
-based visualizations within a
plotgardener
layout. Rather than arranging these plots in a
relative manner, plotgardener
can make and place these
plots in absolute sizes and locations. This makes it simple and
intuitive to make complex and combined
plotgardener
,ggplot
, and other
grid
plot arrangements beyond a basic grid-style
layout.
ggplots
Let’s say we wanted to make a complex multi-panel ggplot
about COVID-19 data consisting of the following plots:
library(ggplot2)
library(scales)
data("COVID_USA_cases")
US_map <- ggplot(COVID_USA_cases, aes(long, lat, group = group)) +
theme_void() +
geom_polygon(aes(fill = cases_100K), color = "white", size = 0.3) +
scale_fill_distiller(
palette = "YlGnBu", direction = 1,
labels = label_number(suffix = "", scale = 1e-3, accuracy = 1)
) +
theme(
legend.position = "left",
legend.justification = c(0.5, 0.95),
legend.title = element_blank(),
legend.text = element_text(size = 7),
legend.key.width = unit(0.3, "cm"),
legend.key.height = unit(0.4, "cm"),
plot.title = element_text(
hjust = 0, vjust = -1,
family = "ProximaNova", face = "bold",
size = 12
),
plot.title.position = "plot"
) +
labs(title = "Thousands of COVID-19 Cases per 100,000 People") +
coord_fixed(1.3)
print(US_map)
data("COVID_NY_FL_tracking")
# Format y-labels
ylabels <- seq(0, 2000000, by = 500000) / 1e6
ylabels[c(3, 5)] <- round(ylabels[c(3, 5)], digits = 0)
ylabels[c(2, 4)] <- round(ylabels[c(2, 4)], digits = 1)
ylabels[5] <- paste0(ylabels[5], "M cases")
ylabels[1] <- ""
casesNY <- COVID_NY_FL_tracking[COVID_NY_FL_tracking$state == "new york", ]
casesNYpoly <- rbind(
casesNY,
data.frame(
"date" = as.Date("2021-03-07"),
"state" = "new york",
"caseIncrease" = -1 * sum(casesNY$caseIncrease)
)
)
cases_NYline <- ggplot(
casesNY,
aes(x = date, y = cumsum(caseIncrease))
) +
geom_polygon(data = casesNYpoly, fill = "#B8E6E6") +
scale_x_date(
labels = date_format("%b '%y"),
breaks = as.Date(c("2020-05-01", "2020-09-01", "2021-01-01")),
limits = as.Date(c("2020-01-29", "2021-03-07")),
expand = c(0, 0)
) +
scale_y_continuous(labels = ylabels, position = "right", expand = c(0, 0)) +
geom_hline(
yintercept = c(500000, 1000000, 1500000, 2000000),
color = "white", linetype = "dashed", size = 0.3
) +
coord_cartesian(ylim = c(0, 2000000)) +
theme(
panel.background = element_rect(fill = "transparent", color = NA),
text = element_text(family = "ProximaNova"),
panel.grid = element_blank(),
panel.border = element_blank(),
plot.background = element_rect(fill = "transparent", color = NA),
axis.line.x.bottom = element_blank(),
axis.line.y = element_line(size = 0.1, color = "#8F9BB3"),
axis.text.x = element_text(
size = 7, hjust = 0.5,
margin = margin(t = -10), color = "black"
),
axis.title.x = element_blank(),
axis.ticks.x = element_line(size = 0.2, color = "black"),
axis.title.y = element_blank(),
axis.text.y = element_text(size = 7, color = "black"),
axis.ticks.y = element_blank(),
axis.ticks.length.x.bottom = unit(-0.1, "cm"),
plot.title = element_text(size = 8, hjust = 1),
plot.title.position = "plot"
)
print(cases_NYline)
casesFL <- COVID_NY_FL_tracking[COVID_NY_FL_tracking$state == "florida", ]
casesFLpoly <- rbind(
casesFL,
data.frame(
"date" = as.Date("2021-03-07"),
"state" = "florida",
"caseIncrease" = -1 * sum(casesFL$caseIncrease)
)
)
cases_FLline <- ggplot(
casesFL,
aes(x = date, y = cumsum(caseIncrease))
) +
geom_polygon(data = casesFLpoly, fill = "#B8E6E6") +
scale_x_date(
labels = date_format("%b '%y"),
breaks = as.Date(c("2020-05-01", "2020-09-01", "2021-01-01")),
limits = as.Date(c("2020-01-29", "2021-03-07")),
expand = c(0, 0)
) +
scale_y_continuous(labels = ylabels, position = "right", expand = c(0, 0)) +
geom_hline(
yintercept = c(500000, 1000000, 1500000, 2000000),
color = "white", linetype = "dashed", size = 0.3
) +
coord_cartesian(ylim = c(0, 2000000)) +
theme(
panel.background = element_rect(fill = "transparent", color = NA),
plot.background = element_rect(fill = "transparent", color = NA),
text = element_text(family = "ProximaNova"),
panel.grid = element_blank(),
panel.border = element_blank(),
axis.line.x.bottom = element_blank(),
axis.line.y = element_line(size = 0.1, color = "#8F9BB3"),
axis.title = element_blank(),
axis.text.y = element_text(size = 7, color = "black"),
axis.text.x = element_text(
size = 7, hjust = 0.5,
margin = margin(t = -10), color = "black"
),
axis.ticks = element_line(color = "black", size = 0.2),
axis.ticks.y = element_blank(),
axis.ticks.length.x.bottom = unit(-0.1, "cm"),
plot.title = element_text(size = 8, hjust = 1),
plot.title.position = "plot"
)
print(cases_FLline)
data("COVID_NY_FL_vaccines")
vaccines_NYpie <- ggplot(
COVID_NY_FL_vaccines[COVID_NY_FL_vaccines$state == "new york", ],
aes(x = "", y = value, fill = vax_group)
) +
geom_bar(width = 1, stat = "identity") +
theme_void() +
scale_fill_manual(values = c("#FBAA7E", "#F7EEBF", "#FBCB88")) +
coord_polar(theta = "y", start = 2.125, clip = "off") +
geom_text(aes(
x = c(1.9, 2, 1.9),
y = c(1.65e7, 1.3e6, 7.8e6),
label = paste0(percent, "%")
),
size = 2.25, color = "black"
) +
theme(
legend.position = "none",
plot.title = element_text(
hjust = 0.5, vjust = -3.5, size = 10,
family = "ProximaNova", face = "bold"
),
text = element_text(family = "ProximaNova")
) +
labs(title = "New York")
print(vaccines_NYpie)
vaccines_FLpie <- ggplot(
COVID_NY_FL_vaccines[COVID_NY_FL_vaccines$state == "florida", ],
aes(x = "", y = value, fill = vax_group)
) +
geom_bar(width = 1, stat = "identity") +
scale_fill_manual(values = c("#FBAA7E", "#F7EEBF", "#FBCB88")) +
theme_void() +
coord_polar(theta = "y", start = pi / 1.78, clip = "off") +
geom_text(aes(
x = c(1.95, 2, 1.9),
y = c(1.9e7, 1.83e6, 9.6e6),
label = paste0(percent, "%")
),
color = "black",
size = 2.25
) +
theme(
legend.position = "none",
plot.title = element_text(
hjust = 0.5, vjust = -4, size = 10,
family = "ProximaNova", face = "bold"
),
text = element_text(family = "ProximaNova")
) +
labs(title = "Florida")
print(vaccines_FLpie)
We can now easily overlap and size all these ggplots
by
passing our saved plot objects into plotGG()
:
pageCreate(width = 9.5, height = 3.5, default.units = "inches")
plotGG(
plot = US_map,
x = 0.1, y = 0,
width = 6.5, height = 3.5, just = c("left", "top")
)
plotGG(
plot = cases_NYline,
x = 6.25, y = 1.8,
width = 3.025, height = 1.4, just = c("left", "bottom")
)
plotGG(
plot = cases_FLline,
x = 6.25, y = 3.5,
width = 3.025, height = 1.4, just = c("left", "bottom")
)
In particular, plotgardener
makes it easy to resize and
place our pie charts in a layout that overlaps our line plots without it
affecting the sizing of the other plots on the page:
plotGG(
plot = vaccines_NYpie,
x = 6.37, y = -0.05,
width = 1.45, height = 1.45, just = c("left", "top")
)
plotGG(
plot = vaccines_FLpie,
x = 6.37, y = 1.67,
width = 1.45, height = 1.45, just = c("left", "top")
)
We can also easily add additional elements to further enhance our
complex ggplot
arrangments, like a precise placement of
text labels:
plotText(
label = c("not", "partially", "fully vaccinated"),
fontfamily = "ProximaNova", fontcolor = "black", fontsize = 7,
x = c(6.58, 7.3, 7.435),
y = c(0.74, 1.12, 0.51), just = c("left", "bottom")
)
plotText(
label = c("not", "partially", "fully vaccinated"),
fontfamily = "ProximaNova", fontcolor = "black", fontsize = 7,
x = c(6.58, 7.39, 7.435),
y = c(2.47, 2.75, 2.2), just = c("left", "bottom")
)
plotText(label = paste("Sources: The COVID Tracking Project;",
"Johns Hopkins Center for Civic Impact"),
fontfamily = "ProximaNova", fontcolor = "black",
fontsize = 7, fontface = "italic",
x = 0.15, y = 3.45, just = c("left", "bottom"))
We are then left with a complex, precise, and elegant arrangement of
ggplots
as if we had arranged them together with graphic
design software:
ComplexHeatmap
Heatmaps are an integral visualization to many multi-panel genomic
visualizations. Existing Bioconductor packages like
ComplexHeatmap
provide excellent methods to produce such
heatmaps. Since these plots are also based on grid
graphics, it is possible to incorporate them into
plotgardener
figure arrangements.
For example, let’s say we made a heatmap representing the density of ChIP-seq data at a particular peak:
library(ComplexHeatmap)
library(purrr)
library(RColorBrewer)
# Simulated data
genmat <- map(
1:2000,
function(i) {
c(sort(abs(rnorm(50)))[1:25], rev(sort(abs(rnorm(50)))[1:25])) * i/5000
}
) %>% do.call(rbind, .)
genmat <- genmat[nrow(genmat):1,]
Heatmap(genmat, col = colorRampPalette(brewer.pal(n = 9, "YlGnBu"))(9),
border = "black",
border_gp = gpar(lwd = 0.5),
show_heatmap_legend = FALSE,
cluster_rows = FALSE, cluster_columns = FALSE)
We can capture this heatmap with the grid
function
grid.grabExpr()
:
library(grid)
heatmap <- grid.grabExpr(draw(Heatmap(genmat,
col = colorRampPalette(brewer.pal(n = 9, "YlGnBu"))(9),
border = "black",
border_gp = gpar(lwd = 0.5),
show_heatmap_legend = FALSE,
cluster_rows = FALSE, cluster_columns = FALSE)))
We can now pass this object into the plotGG
function and
incorporate the heatmap into a plotgardener
layout with
additional figure elements made by plotgardener
:
data("GM12878_HiC_10kb")
data("GM12878_ChIP_CTCF_signal")
data("GM12878_ChIP_H3K27ac_signal")
library("org.Hs.eg.db")
library("TxDb.Hsapiens.UCSC.hg19.knownGene")
## Create page
pageCreate(
width = 6, height = 4, default.units = "inches")
params <- pgParams(chrom = "chr21", chromstart = 28150000, chromend = 29150000,
assembly = "hg19",
x = 0.5, width = 2, default.units = "inches")
ctcf_range <- pgParams(range = c(0, 77),
assembly = "hg19")
hk_range <- pgParams(range = c(0, 32.6),
assembly = "hg19")
hic_gm <- plotHicTriangle(data = GM12878_HiC_10kb, params = params,
zrange = c(0, 200), resolution = 10000,
y = 1.5, height = 1.25, just = c("left", "bottom"))
annoHeatmapLegend(plot = hic_gm, fontsize = 7,
x = 2.5, y = 0.5, width = 0.07, height = 0.5,
just = c("right", "top"), default.units = "inches")
ctcf_gm <- plotSignal(data = GM12878_ChIP_CTCF_signal, params = c(params, ctcf_range),
fill = "#253494", linecolor = "#253494",
y = 1.6, height = 0.6)
plotText(label = "CTCF", fontcolor = "#253494", fontsize = 8,
x = 0.5, y = 1.6, just = c("left","top"), default.units = "inches")
hk_gm <- plotSignal(data = GM12878_ChIP_H3K27ac_signal, params = c(params, hk_range),
fill = "#37a7db", linecolor = "#37a7db",
y = 2.3, height = 0.6, just = c("left", "top"))
plotText(label = "H3K27ac", fontcolor = "#37a7db", fontsize = 8,
x = 0.5, y = 2.4, just = c("left","bottom"), default.units = "inches")
genes_gm <- plotGenes(params = params, stroke = 1, fontsize = 6,
strandLabels = FALSE,
y = 3, height = 0.4)
annoGenomeLabel(plot = genes_gm, params = params,
scale = "Kb", fontsize = 7,
y = 3.5, digits = 0)
## Add ComplexHeatmap
gg_heatmap <- plotGG(
plot = heatmap,
x = 3, y = 0.5,
width = 2.5, height = 3
)
seekViewport(name = "heatmap_matrix_2")
grid.xaxis(at = c(0, 0.5, 1), label = FALSE, gp = gpar(lwd = 0.5))
seekViewport(name = "page")
plotText(label = "Simulated Data", x = 4.25, y = 0.5,
fontsize = 12, just = "bottom")
plotText(label = c(-2, 0, 2), x = c(3.065, 4.255, 5.425),
y = 3.6, fontsize = 7)
plotText(label = "Distance from center", x = 4.25,
y = 3.75, fontsize = 8)
## Hide page guides
pageGuideHide()
sessionInfo()
#> R version 4.3.2 (2023-10-31)
#> Platform: x86_64-apple-darwin20 (64-bit)
#> Running under: macOS Sonoma 14.2.1
#>
#> Matrix products: default
#> BLAS: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRblas.0.dylib
#> LAPACK: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0
#>
#> locale:
#> [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
#>
#> time zone: America/New_York
#> tzcode source: internal
#>
#> attached base packages:
#> [1] stats4 grid stats graphics grDevices utils datasets
#> [8] methods base
#>
#> other attached packages:
#> [1] TxDb.Hsapiens.UCSC.hg19.knownGene_3.2.2
#> [2] GenomicFeatures_1.54.4
#> [3] GenomicRanges_1.54.1
#> [4] GenomeInfoDb_1.38.8
#> [5] org.Hs.eg.db_3.18.0
#> [6] AnnotationDbi_1.64.1
#> [7] IRanges_2.36.0
#> [8] S4Vectors_0.40.2
#> [9] Biobase_2.62.0
#> [10] BiocGenerics_0.48.1
#> [11] RColorBrewer_1.1-3
#> [12] purrr_1.0.2
#> [13] ComplexHeatmap_2.18.0
#> [14] scales_1.3.0
#> [15] ggplot2_3.5.0
#> [16] showtext_0.9-7
#> [17] showtextdb_3.0
#> [18] sysfonts_0.8.9
#> [19] plotgardenerData_1.8.0
#> [20] plotgardener_1.8.2
#>
#> loaded via a namespace (and not attached):
#> [1] strawr_0.0.91 rstudioapi_0.16.0
#> [3] jsonlite_1.8.8 shape_1.4.6.1
#> [5] magrittr_2.0.3 farver_2.1.1
#> [7] rmarkdown_2.26 GlobalOptions_0.1.2
#> [9] fs_1.6.3 BiocIO_1.12.0
#> [11] zlibbioc_1.48.2 ragg_1.3.0
#> [13] vctrs_0.6.5 memoise_2.0.1
#> [15] Rsamtools_2.18.0 RCurl_1.98-1.14
#> [17] htmltools_0.5.8 S4Arrays_1.2.1
#> [19] progress_1.2.3 curl_5.2.1
#> [21] SparseArray_1.2.4 gridGraphics_0.5-1
#> [23] sass_0.4.9 bslib_0.7.0
#> [25] desc_1.4.3 cachem_1.0.8
#> [27] GenomicAlignments_1.38.2 lifecycle_1.0.4
#> [29] iterators_1.0.14 pkgconfig_2.0.3
#> [31] Matrix_1.6-5 R6_2.5.1
#> [33] fastmap_1.1.1 GenomeInfoDbData_1.2.11
#> [35] MatrixGenerics_1.14.0 clue_0.3-65
#> [37] digest_0.6.35 colorspace_2.1-0
#> [39] textshaping_0.3.7 RSQLite_2.3.5
#> [41] filelock_1.0.3 labeling_0.4.3
#> [43] fansi_1.0.6 httr_1.4.7
#> [45] abind_1.4-5 compiler_4.3.2
#> [47] bit64_4.0.5 withr_3.0.0
#> [49] doParallel_1.0.17 BiocParallel_1.36.0
#> [51] DBI_1.2.2 highr_0.10
#> [53] biomaRt_2.58.2 rappdirs_0.3.3
#> [55] DelayedArray_0.28.0 rjson_0.2.21
#> [57] tools_4.3.2 glue_1.7.0
#> [59] restfulr_0.0.15 cluster_2.1.6
#> [61] generics_0.1.3 gtable_0.3.4
#> [63] data.table_1.15.2 hms_1.1.3
#> [65] xml2_1.3.6 utf8_1.2.4
#> [67] XVector_0.42.0 foreach_1.5.2
#> [69] pillar_1.9.0 stringr_1.5.1
#> [71] yulab.utils_0.1.4 circlize_0.4.16
#> [73] dplyr_1.1.4 BiocFileCache_2.10.1
#> [75] lattice_0.22-6 rtracklayer_1.62.0
#> [77] bit_4.0.5 tidyselect_1.2.1
#> [79] Biostrings_2.70.3 knitr_1.45
#> [81] SummarizedExperiment_1.32.0 xfun_0.43
#> [83] matrixStats_1.2.0 stringi_1.8.3
#> [85] yaml_2.3.8 evaluate_0.23
#> [87] codetools_0.2-19 tibble_3.2.1
#> [89] ggplotify_0.1.2 cli_3.6.2
#> [91] systemfonts_1.0.6 munsell_0.5.0
#> [93] jquerylib_0.1.4 Rcpp_1.0.12
#> [95] dbplyr_2.5.0 png_0.1-8
#> [97] XML_3.99-0.16.1 parallel_4.3.2
#> [99] pkgdown_2.0.7 blob_1.2.4
#> [101] prettyunits_1.2.0 plyranges_1.22.0
#> [103] bitops_1.0-7 crayon_1.5.2
#> [105] GetoptLong_1.0.5 rlang_1.1.3
#> [107] KEGGREST_1.42.0