## ----include = FALSE---------------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4 ) ## ----setup-------------------------------------------------------------------- library(rLifting) if (!requireNamespace("ggplot2", quietly = TRUE)) { knitr::opts_chunk$set(eval = FALSE) message("'ggplot2' is required to render plots. Vignette code will not run.") } else { library(ggplot2) } data("benchmark_rlifting", package = "rLifting") set.seed(20260522) ## ----extensions-schematic, echo=FALSE, fig.height=4.5, fig.cap="Figure 1: The five boundary modes applied to a synthetic signal. The original 10 samples are shown in black; the virtual extensions (4 samples on each side) are shown in colour. symmetric mirrors the signal; periodic wraps; zero pads with zero; local_linear extrapolates a line fit through ll_k = 4 boundary samples; one_sided does not extend the signal — instead it renormalises the filter at boundary positions (shown here as 'no extension' for illustration)."---- x = c(1.0, 0.8, 0.6, 0.5, 0.7, 0.9, 1.1, 1.4, 1.5, 1.3) n = length(x) idx_orig = 1:n # Build virtual extensions to display make_ext = function(mode) { left = numeric(4); right = numeric(4) if (mode == "symmetric") { left = rev(x[1:4]); right = rev(x[(n-3):n]) } else if (mode == "periodic") { left = x[(n-3):n]; right = x[1:4] } else if (mode == "zero") { left = rep(0, 4); right = rep(0, 4) } else if (mode == "local_linear") { bL = (sum((0:3) * x[1:4]) - mean(0:3) * sum(x[1:4])) / sum(((0:3) - mean(0:3))^2) aL = mean(x[1:4]) - bL * mean(0:3) left = aL + bL * (-4:-1) bR = (sum((0:3) * x[(n-3):n]) - mean(0:3) * sum(x[(n-3):n])) / sum(((0:3) - mean(0:3))^2) aR = mean(x[(n-3):n]) - bR * mean(0:3) right = aR + bR * (4:7) } else if (mode == "one_sided") { left = rep(NA, 4); right = rep(NA, 4) } data.frame( index = c((-3):0, idx_orig, (n + 1):(n + 4)), value = c(left, x, right), region = c(rep("ext", 4), rep("orig", n), rep("ext", 4)) ) } modes = c("symmetric", "periodic", "zero", "local_linear", "one_sided") df_ext = do.call(rbind, lapply(modes, function(m) { d = make_ext(m); d$mode = m; d })) df_ext$mode = factor(df_ext$mode, levels = modes) ggplot(df_ext, aes(x = index, y = value)) + geom_line( data = subset(df_ext, region == "orig"), colour = "black", linewidth = 0.8 ) + geom_point( data = subset(df_ext, region == "orig"), colour = "black", size = 1.5 ) + geom_line( data = subset(df_ext, region == "ext"), aes(colour = mode), linewidth = 0.8, na.rm = TRUE ) + geom_point( data = subset(df_ext, region == "ext"), aes(colour = mode), size = 1.5, na.rm = TRUE ) + geom_vline( xintercept = c(0.5, n + 0.5), linetype = "dashed", colour = "grey50" ) + facet_wrap(~ mode, ncol = 2) + theme_minimal() + theme(legend.position = "none") + labs( title = "Boundary extensions on a small synthetic signal", subtitle = "Black: original 10 samples. Coloured: virtual extension (4 on each side).", x = "Sample index", y = "Amplitude" ) ## ----offline-boundary-spread-------------------------------------------------- sub_off = subset( benchmark_rlifting, Mode == "offline" & Wavelet == "cdf53" & ThresholdMethod == "universal" & !grepl("tuned", Method) & Shrinkage == "semisoft" ) agg_off = aggregate(MSE_median ~ Signal + Boundary, data = sub_off, FUN = mean) wide_off = reshape( agg_off, idvar = "Signal", timevar = "Boundary", direction = "wide" ) names(wide_off) = sub("MSE_median\\.", "", names(wide_off)) modes_cols = c("symmetric", "periodic", "zero", "local_linear", "one_sided") wide_off$ratio_max_min = round( apply(wide_off[, modes_cols], 1, max) / apply(wide_off[, modes_cols], 1, min), 3 ) wide_off[, c("Signal", modes_cols, "ratio_max_min")] ## ----causal-boundary-haar----------------------------------------------------- sub_haar = subset( benchmark_rlifting, Mode == "causal" & Wavelet == "haar" & ThresholdMethod == "universal" & !grepl("tuned", Method) & Shrinkage == "semisoft" ) agg_haar = aggregate( MSE_settled_median ~ Signal + Boundary, data = sub_haar, FUN = mean ) wide_haar = reshape( agg_haar, idvar = "Signal", timevar = "Boundary", direction = "wide" ) names(wide_haar) = sub("MSE_settled_median\\.", "", names(wide_haar)) wide_haar$ratio_max_min = round( apply(wide_haar[, modes_cols], 1, max) / apply(wide_haar[, modes_cols], 1, min), 3 ) wide_haar[, c("Signal", modes_cols, "ratio_max_min")] ## ----causal-boundary-haar-plot, echo=FALSE, fig.height=4, fig.cap="Figure 2: Causal-mode MSE by boundary across the four DJ signals (haar wavelet, universal threshold, semisoft shrinkage, ll_k = 4). With a single-tap predict filter, one_sided and zero both refuse to invent data at the right boundary and dominate every signal; symmetric pays a 10–50% penalty by mirroring the most recent sample inward."---- df_long_haar = do.call( rbind, lapply( modes_cols, function(b) { data.frame( Signal = wide_haar$Signal, Boundary = b, MSE = wide_haar[[b]] ) } ) ) df_long_haar$Boundary = factor(df_long_haar$Boundary, levels = modes_cols) ggplot(df_long_haar, aes(x = Boundary, y = MSE, fill = Boundary)) + geom_col() + facet_wrap(~ Signal, scales = "free_y", ncol = 4) + scale_fill_brewer(palette = "Set2") + theme_minimal() + theme( legend.position = "none", axis.text.x = element_text(angle = 45, hjust = 1) ) + labs( title = "Causal-mode MSE by boundary (haar, universal/semisoft)", x = NULL, y = "MSE (settled)" ) ## ----causal-boundary-cdf53---------------------------------------------------- sub_cdf = subset( benchmark_rlifting, Mode == "causal" & Wavelet == "cdf53" & ThresholdMethod == "universal" & !grepl("tuned", Method) & Shrinkage == "semisoft" ) agg_cdf = aggregate( MSE_settled_median ~ Signal + Boundary, data = sub_cdf, FUN = mean ) wide_cdf = reshape( agg_cdf, idvar = "Signal", timevar = "Boundary", direction = "wide" ) names(wide_cdf) = sub("MSE_settled_median\\.", "", names(wide_cdf)) wide_cdf$best = modes_cols[apply(wide_cdf[, modes_cols], 1, which.min)] wide_cdf[, c("Signal", modes_cols, "best")]