Files
2026-05-27 21:00:28 +02:00

129 lines
4.4 KiB
R

suppressPackageStartupMessages({
library(argparse)
library(ggplot2)
library(dplyr)
library(tidyr)
library(readr)
library(scales)
library(tikzDevice)
})
SOLUTION_ORDER <- c("tso", "tso-pacing", "cake")
SOLUTION_LABELS <- c(
"no-tso" = "TSO Off",
"tso" = "TSO On",
"tso-pacing" = "TSO Pacing",
"cake" = "Cake"
)
SOLUTION_COLORS <- c(
"no-tso" = "#009E73",
"tso" = "#E69F00",
"tso-pacing" = "#0072B2",
"cake" = "#CC79A7"
)
SOLUTION_LINETYPES <- c(
"no-tso" = "longdash",
"tso" = "dashed",
"tso-pacing" = "solid",
"cake" = "twodash"
)
# Global figure size and font size, overridable via env vars
# (Makefile exports FIG_WIDTH / FIG_HEIGHT / FIG_FONTSIZE).
.env_num <- function(var, default) {
v <- Sys.getenv(var)
if (nchar(v) == 0) default else as.numeric(v)
}
DEFAULT_WIDTH <- .env_num("FIG_WIDTH", 3.33)
DEFAULT_HEIGHT <- .env_num("FIG_HEIGHT", 2.4)
DEFAULT_FONTSIZE <- .env_num("FIG_FONTSIZE", 10)
theme_paper <- function(base_size = DEFAULT_FONTSIZE) {
theme_bw(base_size = base_size) +
theme(
legend.position = "bottom",
legend.title = element_blank(),
legend.margin = margin(t = -4, l = -20),
legend.text = element_text(size = base_size - 1),
legend.key.size = unit(base_size, "pt"),
axis.text = element_text(size = base_size - 1),
strip.background = element_rect(fill = "grey90"),
panel.grid.minor = element_blank(),
plot.margin = margin(2, 4, 2, 2)
)
}
prepare_solution <- function(df) {
df %>%
filter(solution %in% SOLUTION_ORDER) %>%
mutate(solution = factor(solution, levels = SOLUTION_ORDER,
labels = SOLUTION_LABELS[SOLUTION_ORDER]))
}
LABEL_COLORS <- setNames(SOLUTION_COLORS[SOLUTION_ORDER], SOLUTION_LABELS[SOLUTION_ORDER])
LABEL_LINETYPES <- setNames(SOLUTION_LINETYPES[SOLUTION_ORDER], SOLUTION_LABELS[SOLUTION_ORDER])
COL_WIDTH <- 3.33
TEXT_WIDTH <- 7.0
# ACM page-fraction presets, in inches.
HALF_WIDTH <- 3.3 # two figures side-by-side under one \begin{figure}
THIRD_WIDTH <- 2.2 # three figures side-by-side
label_pct <- function() percent_format(accuracy = 1)
label_us <- function() "µs"
pct_sign <- function() "%"
fig_parser <- function(default_width = DEFAULT_WIDTH, default_height = DEFAULT_HEIGHT,
description = "Generate figure") {
p <- ArgumentParser(description = description)
p$add_argument("--data", required = TRUE, help = "derived CSV directory")
p$add_argument("--pdf", help = "write PDF to this path")
p$add_argument("--tikz", help = "write tikz .tex to this path")
p$add_argument("--width", type = "double", default = default_width)
p$add_argument("--height", type = "double", default = default_height)
p$add_argument("--zoom", action = "store_true", help = "use zoomed axis limits")
p$add_argument("--debug-margins", action = "store_true",
help = "color plot.background / panel.background / panel.border to visualise layout")
p
}
# Optional theme overlay that colors the plot canvas, plot panel, and panel
# border so layout / whitespace can be inspected. Returns NULL when off
# (adding NULL to a ggplot is a no-op).
theme_debug_margins <- function(args) {
if (!isTRUE(args$debug_margins)) return(NULL)
theme(
plot.background = element_rect(fill = "#FFF7B3", colour = "black"),
panel.background = element_rect(fill = "#CCE5FF", colour = NA),
panel.border = element_rect(colour = "red", fill = NA, linewidth = 0.6)
)
}
save_figure <- function(plot, args) {
if (is.null(args$pdf) && is.null(args$tikz)) {
stop("save_figure: pass --pdf and/or --tikz")
}
if (!is.null(args$pdf)) {
dir.create(dirname(args$pdf), showWarnings = FALSE, recursive = TRUE)
ggsave(args$pdf, plot, width = args$width, height = args$height, device = "pdf")
message("wrote ", args$pdf)
}
if (!is.null(args$tikz)) {
dir.create(dirname(args$tikz), showWarnings = FALSE, recursive = TRUE)
old <- options(
tikzSanitizeCharacters = c(getOption("tikzSanitizeCharacters"), "µ"),
tikzReplacementCharacters = c(getOption("tikzReplacementCharacters"), "$\\mu$")
)
on.exit(options(old), add = TRUE)
tikz(args$tikz, width = args$width, height = args$height,
standAlone = FALSE, sanitize = TRUE)
print(plot)
dev.off()
message("wrote ", args$tikz)
}
}