diff --git a/scripts/charts/combined_fault_composition.r b/scripts/charts/combined_fault_composition.r new file mode 100644 index 0000000..08bd400 --- /dev/null +++ b/scripts/charts/combined_fault_composition.r @@ -0,0 +1,103 @@ +library(ggplot2) +library(dplyr) +library(readr) +library(stringr) +library(tidyr) + +# Usage: Rscript marker_composition.r exp_abspath1 ... resultsdata_file + +args <- commandArgs(trailingOnly = TRUE) +if (length(args) < 2) { + stop("Need at least 2 experiments") +} + +csv_suffix <- if (grepl("\\.csv$", args[length(args)])) { + args[length(args)] +} else { + "resultsdata.csv" +} +exp_args <- if (grepl("\\.csv$", args[length(args)])) { + args[-length(args)] +} else { + args +} + +extract_info <- function(path) { + dir_name <- basename(path) + match <- str_match( + dir_name, + "^\\d{2}-\\d{2}_\\d{2}-\\d{2}-\\d{2}_(.+?)_(c|aot|interp)_" + ) + if (is.na(match[1, 1])) { + warning(paste("Could not parse:", dir_name)) + return(NULL) + } + list(base_name = match[1, 2], variant = match[1, 3], path = path) +} + +# Load data +all_data <- data.frame() +weight_data <- data.frame() + +for (arg in exp_args) { + info <- extract_info(arg) + if (is.null(info)) { + next + } + + csv_file <- file.path(info$path, csv_suffix) + if (!file.exists(csv_file)) { + warning(paste("Missing:", csv_file)) + next + } + df <- read_csv(csv_file, col_types = cols()) + df$base_name <- info$base_name + df$variant <- info$variant + all_data <- bind_rows(all_data, df) +} + +if (nrow(all_data) == 0) { + stop("No data loaded") +} + +# Skip OK_MARKERs, sum GROUP1 + TRAP. +all_data <- all_data |> + filter(resulttype != "OK_MARKER") |> + mutate( + resulttype = ifelse(resulttype == "GROUP1_MARKER", "TRAP", resulttype) + ) |> + group_by(base_name, variant, benchmark, resulttype) |> + summarise(faults = sum(faults), .groups = "drop") + +out_suffix <- gsub("^resultsdata|\\.csv$", "", csv_suffix) + +# Calculate percentages +composition <- all_data |> + group_by(base_name, variant, benchmark) |> + mutate(frac = faults / sum(faults)) |> + ungroup() + +plot <- ggplot( + composition |> filter(variant %in% c("aot", "interp")), + aes(x = variant, y = frac, fill = resulttype) +) + + geom_col() + + facet_grid(benchmark ~ base_name) + + labs( + title = "Marker Composition (AOT vs Interp)", + x = NULL, + y = "Percentage of Faults", + fill = "Fault Type" + ) + + theme_minimal() + + theme( + plot.title = element_text(size = 13, face = "bold"), + axis.text.x = element_text(angle = 45, hjust = 1) + ) + +filename <- paste0( + "injections/fault_composition", + out_suffix, + ".svg" +) +ggsave(filename, plot = plot, width = 13, height = 8) diff --git a/scripts/charts/combined_instr_fault_rate_heatmap.r b/scripts/charts/combined_instr_fault_rate_heatmap.r deleted file mode 100644 index 39246dc..0000000 --- a/scripts/charts/combined_instr_fault_rate_heatmap.r +++ /dev/null @@ -1,120 +0,0 @@ -library(ggplot2) -library(dplyr) -library(readr) -library(viridisLite) - -# Usage: Rscript combined_instr_fault_correlation_heatmap.r exp_abspath1 ... [faults_file] - -args <- commandArgs(trailingOnly = TRUE) -if (length(args) < 1) { - stop("Need at least 1 experiment") -} - -csv_suffix <- if (grepl("\\.csv$", args[length(args)])) { - args[length(args)] -} else { - "faults.csv" -} -exp_args <- if (grepl("\\.csv$", args[length(args)])) { - args[-length(args)] -} else { - args -} - -all_data <- data.frame() -all_mnem <- data.frame() - -for (arg in exp_args) { - csv_file <- file.path(arg, csv_suffix) - if (!file.exists(csv_file)) { - warning(paste("Missing:", csv_file)) - next - } - - df <- read_csv(csv_file, col_types = cols()) - df$experiment <- basename(arg) - all_data <- bind_rows(all_data, df) - - # TODO: This is ignoring any filters currently - mnem_file <- file.path(arg, "mnemonics.csv") - if (!file.exists(mnem_file)) { - warning(paste("Missing:", mnem_file)) - next - } - mdf <- read_csv(mnem_file, col_types = cols()) - all_mnem <- bind_rows(all_mnem, mdf) -} - -if (nrow(all_data) == 0) { - stop("No faults.csv data loaded") -} - -if (nrow(all_mnem) == 0) { - stop("No mnemonics.csv data loaded") -} - -# no OK_MARKER, sum GROUP1 + TRAP. -all_data <- all_data |> - filter(!is.na(mnemonic), mnemonic != "NULL") |> - filter(resulttype != "OK_MARKER") |> - mutate( - resulttype = ifelse(resulttype == "GROUP1_MARKER", "TRAP", resulttype) - ) - -if (nrow(all_data) == 0) { - stop("No failure-marker data to plot") -} - -# Sum faults per (mnemonic, marker) pair for all experiments -heat <- all_data |> - group_by(mnemonic, resulttype) |> - summarise(faults = sum(faults, na.rm = TRUE), .groups = "drop") - -# Sum mnemonic counts for all experiments -mnem_counts <- all_mnem |> - filter(!is.na(mnemonic), mnemonic != "NULL") |> - group_by(mnemonic) |> - summarise(count = sum(count, na.rm = TRUE), .groups = "drop") - -# Normalize by mnemonic count -heat <- heat |> - left_join(mnem_counts, by = "mnemonic") |> - filter(!is.na(count), count > 0) |> - mutate(fault_rate = faults / count) - -if (nrow(heat) == 0) { - stop("Heat join failed") -} - -# Order by fault rate -mnem_order <- heat |> - group_by(mnemonic) |> - summarise(total = sum(fault_rate), .groups = "drop") |> - arrange(desc(total)) |> - pull(mnemonic) - -heat <- heat |> - mutate(mnemonic = factor(mnemonic, levels = mnem_order)) - -plot <- ggplot( - heat, - aes(x = mnemonic, y = resulttype, fill = fault_rate) -) + - geom_tile(colour = "white") + - scale_fill_viridis_c(name = "Fault rate", trans = "log10") + - labs( - title = "Instruction / Fault Rate Heatmap (Normalized)", - x = "Instruction", - y = "Fault Type" - ) + - theme_minimal() + - theme( - axis.text.x = element_text(angle = 90, hjust = 1), - panel.grid = element_blank(), - plot.title = element_text(size = 14, face = "bold") - ) - -suffix <- gsub("^faults|\\.csv$", "", csv_suffix) -outfile <- paste0("injections/instr_fault_rate_heatmap", suffix, ".svg") -ggsave(outfile, plot = plot, width = 12, height = 6) -print(paste("Saved", outfile))