library(ggplot2) library(dplyr) library(readr) # Usage: Rscript combined_fault_rates.r exp_abspath1 exp_abspath2 ... [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 } # Faults / instruction count, per experiment rates <- data.frame() for (arg in exp_args) { faults_file <- file.path(arg, csv_suffix) mnem_file <- file.path(arg, "mnemonics.csv") if (!file.exists(faults_file)) { warning(paste("Missing:", faults_file)) next } if (!file.exists(mnem_file)) { warning(paste("Missing:", mnem_file)) next } df <- read_csv(faults_file, col_types = cols()) mdf <- read_csv(mnem_file, col_types = cols()) total_faults <- df |> filter(resulttype != "OK_MARKER") |> summarise(faults = sum(faults, na.rm = TRUE)) |> pull(faults) total_instrs <- sum(mdf$count, na.rm = TRUE) if (is.na(total_instrs) || total_instrs == 0) { warning(paste("Zero instruction count for", arg)) next } rates <- bind_rows( rates, data.frame( experiment = basename(arg), fault_rate = total_faults / total_instrs ) ) } if (nrow(rates) == 0) { stop("No data loaded") } # Order by fault rate rates <- rates |> arrange(desc(fault_rate)) |> mutate(experiment = factor(experiment, levels = experiment)) plot <- ggplot( rates, aes(x = experiment, y = fault_rate, fill = experiment) ) + geom_col() + labs( title = "Fault Rate per Instruction", x = "Experiment", y = "Faults / Instruction Count" ) + theme_minimal() + theme( axis.text.x = element_text(angle = 90, hjust = 1), legend.position = "none", plot.title = element_text(size = 14, face = "bold") ) suffix <- gsub("^faults|\\.csv$", "", csv_suffix) outfile <- paste0("injections/fault_rates_per_instruction", suffix, ".svg") ggsave(outfile, plot = plot, width = 12, height = 6) print(paste("Saved", outfile))