Skip to content

Commit 2d4814a

Browse files
committed
merged roc auc plots to summary all folds
1 parent 9e39190 commit 2d4814a

3 files changed

Lines changed: 96 additions & 18 deletions

File tree

bin/roc_curve.R

Lines changed: 87 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,11 @@ compute_auc <- function(roc_df) {
3636
sum((x[-1] - x[-length(x)]) * (y[-1] + y[-length(y)]) / 2)
3737
}
3838

39-
roc_plot <- function(df, output_path = "roc_curve.png") {
39+
compute_roc_and_auc <- function(df) {
4040
if (!all(c("y_true", "y_score") %in% colnames(df))) {
4141
if (!("y_pred" %in% colnames(df))) {
4242
stop("Expected columns y_true and y_score (or y_pred) in input CSV.", call. = FALSE)
4343
}
44-
message("Column y_score not found, using y_pred as score (may degrade ROC).")
4544
df$y_score <- df$y_pred
4645
}
4746

@@ -51,31 +50,106 @@ roc_plot <- function(df, output_path = "roc_curve.png") {
5150
roc_df <- compute_roc(y_true, y_score)
5251
auc <- compute_auc(roc_df)
5352

54-
p <- ggplot(roc_df, aes(x = fpr, y = tpr)) +
55-
geom_line(color = "#67a9cf", size = 1) +
53+
list(roc_df = roc_df, auc = auc)
54+
}
55+
56+
roc_plot_combined <- function(roc_data_list, output_path = "roc_curve.png", title = "ROC Curves") {
57+
# Combine all ROC data with labels
58+
all_roc_data <- data.frame()
59+
60+
for (i in seq_along(roc_data_list)) {
61+
roc_df <- roc_data_list[[i]]$roc_df
62+
auc <- roc_data_list[[i]]$auc
63+
label <- roc_data_list[[i]]$label
64+
65+
# Label format: "fold_num (AUC = X.XXX)"
66+
roc_df$fold <- sprintf("%s (AUC = %.3f)", label, auc)
67+
all_roc_data <- rbind(all_roc_data, roc_df)
68+
}
69+
70+
# Generate color palette
71+
n_folds <- length(roc_data_list)
72+
colors <- rainbow(n_folds)
73+
74+
p <- ggplot(all_roc_data, aes(x = fpr, y = tpr, color = fold)) +
75+
geom_line(linewidth = 1) +
5676
geom_abline(slope = 1, intercept = 0, linetype = "dashed", color = "grey60") +
5777
coord_equal(xlim = c(0, 1), ylim = c(0, 1)) +
78+
scale_color_manual(values = colors, name = "K-Fold") +
5879
labs(
5980
x = "False Positive Rate",
6081
y = "True Positive Rate",
61-
title = sprintf("ROC curve (AUC = %.3f)", auc)
82+
title = title
6283
) +
63-
theme_minimal()
64-
65-
ggsave(output_path, plot = p, width = 6, height = 6, dpi = 300)
84+
theme_minimal() +
85+
theme(
86+
legend.position = "right",
87+
legend.title = element_text(size = 10),
88+
legend.text = element_text(size = 9)
89+
)
90+
91+
ggsave(output_path, plot = p, width = 8, height = 6, dpi = 300)
92+
message(sprintf("Generated combined ROC curve: %s", output_path))
6693
}
6794

6895
main <- function() {
6996
args <- commandArgs(trailingOnly = TRUE)
7097
if (length(args) < 1) {
71-
stop("Usage: Rscript roc_curve.R <test_predictions.csv> [output_path]", call. = FALSE)
98+
stop("Usage: Rscript roc_curve.R <test_predictions1.csv> [test_predictions2.csv ...]", call. = FALSE)
99+
}
100+
101+
csv_files <- args
102+
103+
# Extract feature_extractor and algorithm from first file
104+
# Expected format: {feature_extractor}.{algorithm}.{fold}.test_predictions.csv
105+
first_file <- basename(csv_files[1])
106+
parts <- strsplit(first_file, "\\.")[[1]]
107+
108+
if (length(parts) >= 4) {
109+
feature_extractor <- parts[1]
110+
algorithm <- parts[2]
111+
output_path <- sprintf("%s.%s.roc_auc_curve.png", feature_extractor, algorithm)
112+
} else {
113+
output_path <- "roc_auc_curve.png"
72114
}
73115

74-
test_predictions <- args[1]
75-
output_path <- if (length(args) >= 2) args[2] else "roc_auc_curve.png"
116+
# Process all CSV files and collect ROC data
117+
roc_data_list <- list()
118+
119+
for (csv_file in csv_files) {
120+
if (!file.exists(csv_file)) {
121+
warning(sprintf("File not found: %s, skipping...", csv_file))
122+
next
123+
}
124+
125+
# Read and process
126+
df <- read_csv(csv_file, show_col_types = FALSE)
127+
base_name <- tools::file_path_sans_ext(basename(csv_file))
128+
129+
# Extract fold number from filename (e.g., model.algorithm.0.test_predictions -> 0)
130+
file_parts <- strsplit(base_name, "\\.")[[1]]
131+
if (length(file_parts) >= 3) {
132+
fold_num <- file_parts[3]
133+
label <- fold_num
134+
} else {
135+
# Fallback: try to extract number from end of filename
136+
fold_match <- regmatches(base_name, regexpr("\\d+", base_name))
137+
label <- if (length(fold_match) > 0) fold_match else base_name
138+
}
139+
140+
roc_data <- compute_roc_and_auc(df)
141+
roc_data$label <- label
142+
roc_data_list[[length(roc_data_list) + 1]] <- roc_data
143+
144+
message(sprintf("Processed %s: AUC = %.3f", csv_file, roc_data$auc))
145+
}
146+
147+
if (length(roc_data_list) == 0) {
148+
stop("No valid CSV files found to process.", call. = FALSE)
149+
}
76150

77-
df <- read_csv(test_predictions, show_col_types = FALSE)
78-
roc_plot(df, output_path)
151+
# Generate combined plot
152+
roc_plot_combined(roc_data_list, output_path)
79153
}
80154

81155
if (identical(environment(), globalenv())) {

modules/visualization.nf

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,18 @@ process roc_auc_curve {
3939
path(test_predictions)
4040
path(script_roc_auc_curve)
4141
output:
42-
path("${test_predictions}.roc_auc_curve.png"), emit: roc_auc_curve
42+
path("*.roc_auc_curve.png"), emit: roc_auc_curve
4343
script:
44+
// Output filename is auto-generated by R script as {feature_extractor}.{algorithm}.roc_auc_curve.png
4445
"""
4546
Rscript ${script_roc_auc_curve} $test_predictions
46-
cp roc_auc_curve.png ${test_predictions}.roc_auc_curve.png
4747
"""
4848
stub:
49+
// Extract feature_extractor and algorithm from first file
50+
def parts = test_predictions[0].name.toString().split('\\.')
51+
def feature_extractor = parts[0]
52+
def algorithm = parts[1]
4953
"""
50-
touch ${test_predictions}.roc_auc_curve.png
54+
touch ${feature_extractor}.${algorithm}.roc_auc_curve.png
5155
"""
5256
}

workflows/grid_search.nf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,11 @@ workflow grid_search_workflow {
2020
algorithms = ["elasticnet"]
2121
if (params.task == "classification"){
2222
grid_search(dataset, script_grid_search_classification, algorithms)
23-
roc_auc_curve(grid_search.out.test_predictions.flatten(), script_roc_auc_curve)
23+
roc_auc_curve(grid_search.out.test_predictions, script_roc_auc_curve)
2424
}
2525
else {
2626
grid_search(dataset, script_grid_search_regression, algorithms)
27-
scatterplot(grid_search.out.test_predictions.flatten(), script_scatterplot)
27+
scatterplot(grid_search.out.test_predictions, script_scatterplot)
2828
}
2929
emit:
3030
cv_results = grid_search.out.cv_results

0 commit comments

Comments
 (0)