On linux/rstudio server, rendering plots with longer pattern variable names increase runtime or throw an error
Bug description
I observed that when trying to print a ggplot created with geom_col_pattern, if the levels of the pattern aesthetic were too long, it would throw an error:
Error in seq.default(from, to, by) : invalid '(to - from)/by'
Traceback
35.
stop("invalid '(to - from)/by'")
34.
seq.default(from, to, by)
33.
seq(from, to, by) at
utils-geometry.R#108
32.
seq_robust(from = 0, to = gm * vpm$length + x_adjust, by = h_spacing) at
pattern-geometry-regular_polygon.R#276
31.
get_xy_grid(params, vpm) at
pattern-geometry-crosshatch.R#56
30.
create_crosshatch_via_sf_helper(params, boundary_df, add_top_hatch = FALSE) at
pattern-geometry-stripe.R#39
29.
fn(params, boundary_df, aspect_ratio, x$legend) at
grid-pattern.R#171
28.
makeContent.pattern(x)
27.
makeContent(x)
26.
drawGTree(x)
25.
recordGraphics(drawGTree(x), list(x = x), getNamespace("grid"))
24.
grid.draw.gTree(x$children[[i]], recording = FALSE)
23.
grid.draw(x$children[[i]], recording = FALSE)
22.
drawGTree(x)
21.
recordGraphics(drawGTree(x), list(x = x), getNamespace("grid"))
20.
grid.draw.gTree(x$children[[i]], recording = FALSE)
19.
grid.draw(x$children[[i]], recording = FALSE)
18.
drawGTree(x)
17.
recordGraphics(drawGTree(x), list(x = x), getNamespace("grid"))
16.
grid.draw.gTree(x$children[[i]], recording = FALSE)
15.
grid.draw(x$children[[i]], recording = FALSE)
14.
drawGTree(x)
13.
recordGraphics(drawGTree(x), list(x = x), getNamespace("grid"))
12.
grid.draw.gTree(x$children[[i]], recording = FALSE)
11.
grid.draw(x$children[[i]], recording = FALSE)
10.
drawGTree(x)
9.
recordGraphics(drawGTree(x), list(x = x), getNamespace("grid"))
8.
grid.draw.gTree(x$children[[i]], recording = FALSE)
7.
grid.draw(x$children[[i]], recording = FALSE)
6.
drawGTree(x)
5.
recordGraphics(drawGTree(x), list(x = x), getNamespace("grid"))
4.
grid.draw.gTree(gtable)
3.
grid.draw(gtable)
2.
print.ggplot(x)
1.
(function (x, ...)
UseMethod("print"))(x)
I played around with some different settings for the variable length, as well as the font size. It seems to be specifically an issue with rendering the plot (as removing the 'print' call can allow the code to run). Interestingly, the issue does NOT occur on my local Mac. I thought maybe it had to do with the graphics backend on my RStudio server instance (ran on Linux), so I switched from AGG to Cairo, but the issue persisted. This may not be an issue with ggpattern itself, as there may be other factors relating to the image rendering that I don't know about, but I have been working on this dockerized RStudio server instance for months and never had a similar issue with other plots.
Minimal, reproducible example
code
# Setup ----
if (!require('tidyverse')) {
install.packages('tidyverse')
}
if (!require('remotes')) {
install.packages('remotes')
}
if (!require('ggpattern')) {
remotes::install_github("coolbutuseless/ggpattern")
}
library(tidyverse)
library(ggpattern)
# Functions ----
basic_plot <- function(plot.data=plotdata, base_size=11){ # 11 is default base size
print(ggplot(plot.data, aes(x=group, y=value, group=pattern_variable)) +
geom_col_pattern(aes(pattern=pattern_variable), position='identity') +
theme_bw(base_size=base_size)
)
}
time_plotting <- function(plot.data=plotdata, base_size=11){
tryCatch({
start <- Sys.time()
basic_plot(plot.data, base_size=base_size)
end <- Sys.time()
return(end - start)
}, error=function(e){
print(e)
return(NA)
})
}
# Plotdata ----
plotdata <- data.frame(group=c(rep(c(1,2),2)),
pattern_variable=as.factor(c(rep('group_A',2), rep('group_B',2))),
value=c(0.39, 0.31, 0.13, 0.12))
# Demo ----
## Rendering plots with long strings works fine out of the box
time_plotting()
## Changing the length of the pattern variable names increases runtime
plotdata$pattern_variable <- as.factor(c(rep('looooooong_group_name',2),
rep('short_name',2)))
time_plotting()
## Altering the base theme to modify the text size also increases runtime
plotdata$pattern_variable <- as.factor(c(rep('group_A',2), rep('group_B',2)))
time_plotting(base_size = 14)
## Exploring a range of string lengths in case it behaves differently on your machine
timing <- data.frame(string_length = seq(10, 20, 2))
timing$time <- rep(NA, length(timing$string_length))
for (i in 1:nrow(timing)) {
plotdata$pattern_variable <- c(as.factor(rep(paste0(rep('X', timing$string_length[i]), collapse=''),2)),
as.factor(rep('short_name', 2)))
timing$time[i] <- time_plotting()
}
timing
## Exploring a range of font sizes in case it behaves differently on your machine
plotdata$pattern_variable <- c(as.factor(rep('medium_len_string',2)),
as.factor(rep('short_string', 2)))
timing <- data.frame(base_size = seq(11,17,2))
timing$time <- rep(NA, length(timing$base_size))
for (i in 1:nrow(timing)) {
timing$time[i] <- time_plotting(base_size = timing$base_size[i])
}
timing
Session info
Session info for linux session:
R version 4.4.0 (2024-04-24)
Platform: x86_64-pc-linux-gnu
Running under: Ubuntu 18.04.6 LTS, RStudio c(2024, 5, 999, 999)
Locale:
LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8 LC_MONETARY=en_US.UTF-8
LC_MESSAGES=en_US.UTF-8 LC_PAPER=en_US.UTF-8 LC_NAME=C LC_ADDRESS=C LC_TELEPHONE=C
LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
Package version:
cachem_1.1.0 class_7.3.22 classInt_0.4.10 cli_3.6.3 colorspace_2.1.0 DBI_1.2.2 e1071_1.7.14
fansi_1.0.6 farver_2.1.2 fastmap_1.2.0 ggpattern_1.1.4 ggplot2_3.5.1 glue_1.8.0 graphics_4.4.0
grDevices_4.4.0 grid_4.4.0 gridpattern_1.3.1 gtable_0.3.5 isoband_0.2.7 KernSmooth_2.23.22 labeling_0.4.3
lattice_0.22.6 lifecycle_1.0.4 magrittr_2.0.3 MASS_7.3.60.2 Matrix_1.7.1 memoise_2.0.1 methods_4.4.0
mgcv_1.9.1 munsell_0.5.1 nlme_3.1.164 pillar_1.9.0 pkgconfig_2.0.3 png_0.1.8 proxy_0.4.27
R6_2.5.1 RColorBrewer_1.1.3 Rcpp_1.0.13 rlang_1.1.4 s2_1.1.6 scales_1.3.0 sf_1.0.16
splines_4.4.0 stats_4.4.0 tibble_3.2.1 tools_4.4.0 units_0.8.5 utf8_1.2.4 utils_4.4.0
vctrs_0.6.5 viridisLite_0.4.2 withr_3.0.0 wk_0.9.1
Session info for Mac session:
R version 4.4.1 (2024-06-14)
Platform: aarch64-apple-darwin20
Running under: macOS 15.3.2, RStudio 2024.9.1.394
Locale: en_US.UTF-8 / en_US.UTF-8 / en_US.UTF-8 / C / en_US.UTF-8 / en_US.UTF-8
Package version:
cachem_1.1.0 class_7.3.22 classInt_0.4.10 cli_3.6.3
colorspace_2.1.1 DBI_1.2.3 e1071_1.7.16 fansi_1.0.6
farver_2.1.2 fastmap_1.2.0 ggpattern_1.1.4 ggplot2_3.5.1
glue_1.7.0 graphics_4.4.1 grDevices_4.4.1 grid_4.4.1
gridpattern_1.3.1 gtable_0.3.5 isoband_0.2.7 KernSmooth_2.23.24
labeling_0.4.3 lattice_0.22.6 lifecycle_1.0.4 magrittr_2.0.3
MASS_7.3.61 Matrix_1.7.0 memoise_2.0.1 methods_4.4.1
mgcv_1.9.1 munsell_0.5.1 nlme_3.1.166 pillar_1.9.0
pkgconfig_2.0.3 png_0.1.8 proxy_0.4.27 R6_2.5.1
RColorBrewer_1.1.3 Rcpp_1.0.13 rlang_1.1.4 s2_1.1.7
scales_1.3.0 sf_1.0.17 splines_4.4.1 stats_4.4.1
tibble_3.2.1 tools_4.4.1 units_0.8.5 utf8_1.2.4
utils_4.4.1 vctrs_0.6.5 viridisLite_0.4.2 withr_3.0.1
wk_0.9.3
additional context:
It seems to write to memory or write to files fine, it's just rendering it in the Rstudio server viewport. It also seems to scale with the total amount of patterns rendered: when I used it in a facet it seems to take even longer.
it's just rendering it in the Rstudio server viewport
- What graphics device exactly are you using? Perhaps try
print(dev.cur())anddev.capabilities()? - Have you tried changing the graphics backend default in Rstudio server? Besides
ragg::agg_png()what aboutpng(type = "cairo")? https://ragg.r-lib.org/#use-ragg-in-rstudio - What happens if you use
dev.new(noRstudioGD = TRUE)?
What timings exactly do you see? I don't really see any huge changes in timing (or errors) that you observe on my Pop OS (debian-based Linux distro) laptop i.e. for the three time_plotting() calls in your example I observe 0.1464, 0.1401, and 0.1718 seconds when using the X11 cairo device.
Also you can try to use scale_pattern_manual() to try to use different patterns...