From 4e437a0911ad76ef04fdb1cb9a13c1fa894c0ef2 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Mon, 29 Jun 2026 17:36:03 -0400 Subject: [PATCH 01/13] Update count_type to list with raw, clean, filt, norm options (default: filt) --- .codeocean/app-panel.json | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.codeocean/app-panel.json b/.codeocean/app-panel.json index 269c50d..9a10b0d 100644 --- a/.codeocean/app-panel.json +++ b/.codeocean/app-panel.json @@ -37,9 +37,15 @@ "name": "Count type", "param_name": "count_type", "description": "Type of counts to use (e.g., filt, norm)", - "type": "text", + "type": "list", "value_type": "string", - "default_value": "filt" + "default_value": "filt", + "extra_data": [ + "raw", + "clean", + "filt", + "norm" + ] }, { "id": "sub_count_type_id", From d43594d51df90d65ad28041f2160899ef9e9c8af Mon Sep 17 00:00:00 2001 From: phoman14 Date: Mon, 29 Jun 2026 18:00:52 -0400 Subject: [PATCH 02/13] Move count_type to first position in Basic category --- .codeocean/app-panel.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.codeocean/app-panel.json b/.codeocean/app-panel.json index 9a10b0d..f3cf723 100644 --- a/.codeocean/app-panel.json +++ b/.codeocean/app-panel.json @@ -16,24 +16,24 @@ "id": "7Rr6IxOMDucKMImp", "name": "Input Data Parameters", "description": "Options for defining input data", - "icon": "📁" + "icon": "\ud83d\udcc1" }, { "id": "EzTg1ivlFDHEy9PI", "name": "Basic", - "icon": "📂" + "icon": "\ud83d\udcc2" }, { "id": "FvI4Z2eb9sjL47Jt", "name": "Visualization", "description": "Visualization and plotting options", - "icon": "📊" + "icon": "\ud83d\udcca" } ], "parameters": [ { "id": "count_type_id", - "category": "FvI4Z2eb9sjL47Jt", + "category": "EzTg1ivlFDHEy9PI", "name": "Count type", "param_name": "count_type", "description": "Type of counts to use (e.g., filt, norm)", @@ -159,4 +159,4 @@ "file_name": "figures/pca/pca_3D.html" } ] -} \ No newline at end of file +} From 0a8630ab09009c58a9df60138785742a24240680 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Tue, 30 Jun 2026 04:02:49 -0400 Subject: [PATCH 03/13] Reorganize PCA 3D panel categories --- .codeocean/app-panel.json | 76 +++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/.codeocean/app-panel.json b/.codeocean/app-panel.json index f3cf723..eea2542 100644 --- a/.codeocean/app-panel.json +++ b/.codeocean/app-panel.json @@ -12,12 +12,6 @@ } ], "categories": [ - { - "id": "7Rr6IxOMDucKMImp", - "name": "Input Data Parameters", - "description": "Options for defining input data", - "icon": "\ud83d\udcc1" - }, { "id": "EzTg1ivlFDHEy9PI", "name": "Basic", @@ -28,6 +22,12 @@ "name": "Visualization", "description": "Visualization and plotting options", "icon": "\ud83d\udcca" + }, + { + "id": "7Rr6IxOMDucKMImp", + "name": "Advanced", + "description": "Advanced input data options", + "icon": "\ud83d\udcc1" } ], "parameters": [ @@ -47,27 +47,38 @@ "norm" ] }, + { + "id": "group_colname_id", + "category": "EzTg1ivlFDHEy9PI", + "name": "Group column name", + "param_name": "group_colname", + "description": "Column name for sample groups", + "type": "text", + "value_type": "string", + "default_value": "Group" + }, + { + "id": "label_colname_id", + "category": "EzTg1ivlFDHEy9PI", + "name": "Label column name", + "param_name": "label_colname", + "description": "Column name for sample labels", + "type": "text", + "value_type": "string", + "default_value": "Label" + }, { "id": "sub_count_type_id", - "category": "FvI4Z2eb9sjL47Jt", + "category": "7Rr6IxOMDucKMImp", "name": "Sub count type", "param_name": "sub_count_type", "description": "Sub count type if count_type is a list", "type": "text", "value_type": "string" }, - { - "id": "feature_id_colname_id", - "category": "FvI4Z2eb9sjL47Jt", - "name": "Feature ID column name", - "param_name": "feature_id_colname", - "description": "Column name for feature IDs", - "type": "text", - "value_type": "string" - }, { "id": "sample_id_colname_id", - "category": "FvI4Z2eb9sjL47Jt", + "category": "EzTg1ivlFDHEy9PI", "name": "Sample ID column name", "param_name": "sample_id_colname", "description": "Column name for sample IDs", @@ -83,29 +94,9 @@ "type": "text", "value_type": "string" }, - { - "id": "group_colname_id", - "category": "7Rr6IxOMDucKMImp", - "name": "Group column name", - "param_name": "group_colname", - "description": "Column name for sample groups", - "type": "text", - "value_type": "string", - "default_value": "Group" - }, - { - "id": "label_colname_id", - "category": "7Rr6IxOMDucKMImp", - "name": "Label column name", - "param_name": "label_colname", - "description": "Column name for sample labels", - "type": "text", - "value_type": "string", - "default_value": "Label" - }, { "id": "principal_components_id", - "category": "EzTg1ivlFDHEy9PI", + "category": "7Rr6IxOMDucKMImp", "name": "Principal components", "param_name": "principal_components", "description": "Principal components to plot (comma-separated, e.g., 1,2,3)", @@ -113,6 +104,15 @@ "value_type": "string", "default_value": "1,2,3" }, + { + "id": "feature_id_colname_id", + "category": "7Rr6IxOMDucKMImp", + "name": "Feature ID column name", + "param_name": "feature_id_colname", + "description": "Column name for feature IDs", + "type": "text", + "value_type": "string" + }, { "id": "point_size_id", "category": "FvI4Z2eb9sjL47Jt", From c4cac187e50617ca1da32f9ce7ac146678a63164 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Tue, 30 Jun 2026 13:40:55 -0400 Subject: [PATCH 04/13] Update changelog for parameter UI changes --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e7b785..69f720f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Code Ocean capsule - MOSuite - plot 3D PCA +## Development version + +- Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1). + ## v2.0 - Use MOSuite v0.3.0. @@ -9,4 +13,4 @@ Initial release - \ No newline at end of file + From 3f54e6590c3f3a4844768123fbdc885ac0e48fc7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 17:41:11 +0000 Subject: [PATCH 05/13] `air format` (GitHub Actions) --- code/main.R | 107 ++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 82 insertions(+), 25 deletions(-) diff --git a/code/main.R b/code/main.R index a290cd4..940db70 100644 --- a/code/main.R +++ b/code/main.R @@ -13,18 +13,73 @@ setup_capsule_environment() # parse CLI arguments parser <- ArgumentParser() -parser$add_argument("--count_type", type="character", default="filt") -parser$add_argument("--sub_count_type", type="character", default=NULL, help="Sub count type if count_type is a list") -parser$add_argument("--feature_id_colname", type="character", default=NULL, help="Column name for feature IDs") -parser$add_argument("--sample_id_colname", type="character", default=NULL, help="Column name for sample IDs") -parser$add_argument("--samples_to_rename", type="character", default="", help="Samples to rename in format old:new,old2:new2") -parser$add_argument("--group_colname", type="character", default="Group", help="Column name for sample groups") -parser$add_argument("--label_colname", type="character", default="Label", help="Column name for sample labels") -parser$add_argument("--principal_components", type="character", default="1,2,3", help="Principal components to plot (comma-separated)") -parser$add_argument("--point_size", type="integer", default=8, help="Size of points in plot") -parser$add_argument("--label_font_size", type="integer", default=24, help="Font size for labels") -parser$add_argument("--color_values", type="character", default="#5954d6,#e1562c,#b80058,#00c6f8,#d163e6,#00a76c,#ff9287,#008cf9,#006e00,#796880,#FFA500,#878500", help="Comma-separated color values") -parser$add_argument("--plot_title", type="character", default="PCA 3D", help="Title for the plot") +parser$add_argument("--count_type", type = "character", default = "filt") +parser$add_argument( + "--sub_count_type", + type = "character", + default = NULL, + help = "Sub count type if count_type is a list" +) +parser$add_argument( + "--feature_id_colname", + type = "character", + default = NULL, + help = "Column name for feature IDs" +) +parser$add_argument( + "--sample_id_colname", + type = "character", + default = NULL, + help = "Column name for sample IDs" +) +parser$add_argument( + "--samples_to_rename", + type = "character", + default = "", + help = "Samples to rename in format old:new,old2:new2" +) +parser$add_argument( + "--group_colname", + type = "character", + default = "Group", + help = "Column name for sample groups" +) +parser$add_argument( + "--label_colname", + type = "character", + default = "Label", + help = "Column name for sample labels" +) +parser$add_argument( + "--principal_components", + type = "character", + default = "1,2,3", + help = "Principal components to plot (comma-separated)" +) +parser$add_argument( + "--point_size", + type = "integer", + default = 8, + help = "Size of points in plot" +) +parser$add_argument( + "--label_font_size", + type = "integer", + default = 24, + help = "Font size for labels" +) +parser$add_argument( + "--color_values", + type = "character", + default = "#5954d6,#e1562c,#b80058,#00c6f8,#d163e6,#00a76c,#ff9287,#008cf9,#006e00,#796880,#FFA500,#878500", + help = "Comma-separated color values" +) +parser$add_argument( + "--plot_title", + type = "character", + default = "PCA 3D", + help = "Title for the plot" +) args <- parser$parse_args() @@ -33,17 +88,19 @@ moo <- load_moo_from_data_dir() # run MOSuite plot_pca( - moo, - count_type = args$count_type, - sub_count_type = args$sub_count_type, - principal_components = as.integer(parse_optional_vector(args$principal_components)), - feature_id_colname = args$feature_id_colname, - sample_id_colname = args$sample_id_colname, - samples_to_rename = parse_samples_to_rename(args$samples_to_rename), - group_colname = args$group_colname, - label_colname = args$label_colname, - point_size = args$point_size, - label_font_size = args$label_font_size, - color_values = parse_optional_vector(args$color_values), - plot_title = args$plot_title + moo, + count_type = args$count_type, + sub_count_type = args$sub_count_type, + principal_components = as.integer(parse_optional_vector( + args$principal_components + )), + feature_id_colname = args$feature_id_colname, + sample_id_colname = args$sample_id_colname, + samples_to_rename = parse_samples_to_rename(args$samples_to_rename), + group_colname = args$group_colname, + label_colname = args$label_colname, + point_size = args$point_size, + label_font_size = args$label_font_size, + color_values = parse_optional_vector(args$color_values), + plot_title = args$plot_title ) From c38085a89c7fb19bf15d2f0d29bd4e6e95d5f0c0 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Tue, 30 Jun 2026 14:11:01 -0400 Subject: [PATCH 06/13] Add author handle to changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69f720f..11bdfd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Development version -- Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1). +- Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1, @phoman14). ## v2.0 From cc765b01b8729771b160d97b7b2000da0c9920cc Mon Sep 17 00:00:00 2001 From: phoman14 Date: Tue, 30 Jun 2026 15:52:06 -0400 Subject: [PATCH 07/13] Add PCA 3D capsule tests --- CHANGELOG.md | 1 + tests/test-setup.R | 7 +++++ tests/testthat.R | 3 ++ tests/testthat/helper-panel.R | 54 +++++++++++++++++++++++++++++++++++ tests/testthat/test-main.R | 54 +++++++++++++++++++++++++++++++++++ 5 files changed, 119 insertions(+) create mode 100644 tests/test-setup.R create mode 100644 tests/testthat.R create mode 100644 tests/testthat/helper-panel.R create mode 100644 tests/testthat/test-main.R diff --git a/CHANGELOG.md b/CHANGELOG.md index 11bdfd3..8d24f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Development version +- Added tests for the plot pca 3D capsule Code Ocean panel and CLI contract (#1, @phoman14). - Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1, @phoman14). ## v2.0 diff --git a/tests/test-setup.R b/tests/test-setup.R new file mode 100644 index 0000000..c31f6b8 --- /dev/null +++ b/tests/test-setup.R @@ -0,0 +1,7 @@ +testthat::test_that("test setup has expected capsule files", { + repo_root <- normalizePath(file.path(testthat::test_path(), "..", "..")) + + testthat::expect_true(file.exists(file.path(repo_root, "code", "main.R"))) + testthat::expect_true(file.exists(file.path(repo_root, "code", "run"))) + testthat::expect_true(file.exists(file.path(repo_root, ".codeocean", "app-panel.json"))) +}) \ No newline at end of file diff --git a/tests/testthat.R b/tests/testthat.R new file mode 100644 index 0000000..aca735a --- /dev/null +++ b/tests/testthat.R @@ -0,0 +1,3 @@ +library(testthat) + +test_dir(file.path("tests", "testthat")) \ No newline at end of file diff --git a/tests/testthat/helper-panel.R b/tests/testthat/helper-panel.R new file mode 100644 index 0000000..2d8d52d --- /dev/null +++ b/tests/testthat/helper-panel.R @@ -0,0 +1,54 @@ +repo_path <- function(...) { + file.path(normalizePath(file.path(testthat::test_path(), "..", "..")), ...) +} + +read_repo_file <- function(...) { + readLines(repo_path(...), warn = FALSE) +} + +extract_main_arguments <- function(main_lines) { + main_text <- paste(main_lines, collapse = "\n") + matches <- regmatches( + main_text, + gregexpr( + 'parser\\$add_argument\\(\\s*"--([[:alnum:]_]+)"', + main_text, + perl = TRUE + ) + )[[1]] + + sub('.*"--([[:alnum:]_]+)".*', "\\1", matches) +} + +extract_panel_param_names <- function(panel_lines) { + matches <- regmatches( + panel_lines, + gregexpr('"param_name"[[:space:]]*:[[:space:]]*"([[:alnum:]_]+)"', panel_lines) + ) + matches <- unlist(matches, use.names = FALSE) + + sub('.*"param_name"[[:space:]]*:[[:space:]]*"([[:alnum:]_]+)".*', "\\1", matches) +} + +extract_panel_default <- function(panel_lines, param_name) { + param_line <- grep(sprintf('"param_name"[[:space:]]*:[[:space:]]*"%s"', param_name), panel_lines) + if (length(param_line) != 1) { + return(NA_character_) + } + + next_param <- grep('"param_name"[[:space:]]*:', panel_lines) + next_param <- next_param[next_param > param_line] + end_line <- if (length(next_param) > 0) next_param[[1]] - 1 else length(panel_lines) + block <- panel_lines[param_line:end_line] + default_line <- grep('"default_value"[[:space:]]*:', block, value = TRUE) + if (length(default_line) != 1) { + return(NA_character_) + } + + sub('.*"default_value"[[:space:]]*:[[:space:]]*"([^"]*)".*', "\\1", default_line) +} + +expect_same_values <- function(actual, expected, info = NULL) { + testthat::expect_setequal(actual, expected) + testthat::expect_equal(length(actual), length(unique(actual)), info = "Values should not be duplicated") +} \ No newline at end of file diff --git a/tests/testthat/test-main.R b/tests/testthat/test-main.R new file mode 100644 index 0000000..595bf89 --- /dev/null +++ b/tests/testthat/test-main.R @@ -0,0 +1,54 @@ +test_that("Code Ocean panel uses named parameters accepted by main.R", { + main_args <- extract_main_arguments(read_repo_file("code", "main.R")) + panel_lines <- read_repo_file(".codeocean", "app-panel.json") + panel_args <- extract_panel_param_names(panel_lines) + + expect_true( + any(grepl('"named_parameters"[[:space:]]*:[[:space:]]*true', panel_lines)), + info = "Code Ocean should pass parameters by name to main.R" + ) + expect_same_values( + panel_args, + main_args, + info = "Every app-panel param_name should match a main.R CLI argument" + ) +}) + +test_that("3D PCA capsule keeps expected PCA parameter contract", { + main_lines <- read_repo_file("code", "main.R") + panel_lines <- read_repo_file(".codeocean", "app-panel.json") + + shared_pca_args <- c( + "count_type", + "sub_count_type", + "feature_id_colname", + "sample_id_colname", + "samples_to_rename", + "group_colname", + "label_colname", + "principal_components", + "point_size", + "label_font_size", + "color_values" + ) + three_dimensional_args <- "plot_title" + + expect_same_values( + extract_main_arguments(main_lines), + c(shared_pca_args, three_dimensional_args), + info = "3D PCA main.R should expose shared PCA args plus 3D-specific controls" + ) + expect_match(paste(main_lines, collapse = "\n"), "plot_pca\\(") + expect_equal(extract_panel_default(panel_lines, "principal_components"), "1,2,3") + expect_equal(extract_panel_default(panel_lines, "point_size"), "8") + expect_equal(extract_panel_default(panel_lines, "label_font_size"), "24") + expect_equal(extract_panel_default(panel_lines, "plot_title"), "PCA 3D") +}) + +test_that("run wrapper prepares result directories and forwards CLI arguments", { + run_lines <- read_repo_file("code", "run") + run_text <- paste(run_lines, collapse = "\n") + + expect_match(run_text, "mkdir -p \\.\\./results/figures \\.\\./results/moo") + expect_match(run_text, 'Rscript main\\.R "\\$@"') +}) \ No newline at end of file From 5248722a9c7f9e58bd88e62e8f6a965fd96a1a65 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 30 Jun 2026 19:52:21 +0000 Subject: [PATCH 08/13] `air format` (GitHub Actions) --- tests/test-setup.R | 8 ++++++-- tests/testthat.R | 2 +- tests/testthat/helper-panel.R | 36 ++++++++++++++++++++++++++++------- tests/testthat/test-main.R | 7 +++++-- 4 files changed, 41 insertions(+), 12 deletions(-) diff --git a/tests/test-setup.R b/tests/test-setup.R index c31f6b8..dc1ce41 100644 --- a/tests/test-setup.R +++ b/tests/test-setup.R @@ -3,5 +3,9 @@ testthat::test_that("test setup has expected capsule files", { testthat::expect_true(file.exists(file.path(repo_root, "code", "main.R"))) testthat::expect_true(file.exists(file.path(repo_root, "code", "run"))) - testthat::expect_true(file.exists(file.path(repo_root, ".codeocean", "app-panel.json"))) -}) \ No newline at end of file + testthat::expect_true(file.exists(file.path( + repo_root, + ".codeocean", + "app-panel.json" + ))) +}) diff --git a/tests/testthat.R b/tests/testthat.R index aca735a..fa13c48 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,3 +1,3 @@ library(testthat) -test_dir(file.path("tests", "testthat")) \ No newline at end of file +test_dir(file.path("tests", "testthat")) diff --git a/tests/testthat/helper-panel.R b/tests/testthat/helper-panel.R index 2d8d52d..fbf5a2d 100644 --- a/tests/testthat/helper-panel.R +++ b/tests/testthat/helper-panel.R @@ -23,32 +23,54 @@ extract_main_arguments <- function(main_lines) { extract_panel_param_names <- function(panel_lines) { matches <- regmatches( panel_lines, - gregexpr('"param_name"[[:space:]]*:[[:space:]]*"([[:alnum:]_]+)"', panel_lines) + gregexpr( + '"param_name"[[:space:]]*:[[:space:]]*"([[:alnum:]_]+)"', + panel_lines + ) ) matches <- unlist(matches, use.names = FALSE) - sub('.*"param_name"[[:space:]]*:[[:space:]]*"([[:alnum:]_]+)".*', "\\1", matches) + sub( + '.*"param_name"[[:space:]]*:[[:space:]]*"([[:alnum:]_]+)".*', + "\\1", + matches + ) } extract_panel_default <- function(panel_lines, param_name) { - param_line <- grep(sprintf('"param_name"[[:space:]]*:[[:space:]]*"%s"', param_name), panel_lines) + param_line <- grep( + sprintf('"param_name"[[:space:]]*:[[:space:]]*"%s"', param_name), + panel_lines + ) if (length(param_line) != 1) { return(NA_character_) } next_param <- grep('"param_name"[[:space:]]*:', panel_lines) next_param <- next_param[next_param > param_line] - end_line <- if (length(next_param) > 0) next_param[[1]] - 1 else length(panel_lines) + end_line <- if (length(next_param) > 0) { + next_param[[1]] - 1 + } else { + length(panel_lines) + } block <- panel_lines[param_line:end_line] default_line <- grep('"default_value"[[:space:]]*:', block, value = TRUE) if (length(default_line) != 1) { return(NA_character_) } - sub('.*"default_value"[[:space:]]*:[[:space:]]*"([^"]*)".*', "\\1", default_line) + sub( + '.*"default_value"[[:space:]]*:[[:space:]]*"([^"]*)".*', + "\\1", + default_line + ) } expect_same_values <- function(actual, expected, info = NULL) { testthat::expect_setequal(actual, expected) - testthat::expect_equal(length(actual), length(unique(actual)), info = "Values should not be duplicated") -} \ No newline at end of file + testthat::expect_equal( + length(actual), + length(unique(actual)), + info = "Values should not be duplicated" + ) +} diff --git a/tests/testthat/test-main.R b/tests/testthat/test-main.R index 595bf89..9ce5907 100644 --- a/tests/testthat/test-main.R +++ b/tests/testthat/test-main.R @@ -39,7 +39,10 @@ test_that("3D PCA capsule keeps expected PCA parameter contract", { info = "3D PCA main.R should expose shared PCA args plus 3D-specific controls" ) expect_match(paste(main_lines, collapse = "\n"), "plot_pca\\(") - expect_equal(extract_panel_default(panel_lines, "principal_components"), "1,2,3") + expect_equal( + extract_panel_default(panel_lines, "principal_components"), + "1,2,3" + ) expect_equal(extract_panel_default(panel_lines, "point_size"), "8") expect_equal(extract_panel_default(panel_lines, "label_font_size"), "24") expect_equal(extract_panel_default(panel_lines, "plot_title"), "PCA 3D") @@ -51,4 +54,4 @@ test_that("run wrapper prepares result directories and forwards CLI arguments", expect_match(run_text, "mkdir -p \\.\\./results/figures \\.\\./results/moo") expect_match(run_text, 'Rscript main\\.R "\\$@"') -}) \ No newline at end of file +}) From 5a35adf0111b1255053cb8bd20f1b52ec3cbde3c Mon Sep 17 00:00:00 2001 From: phoman14 Date: Tue, 30 Jun 2026 16:04:24 -0400 Subject: [PATCH 09/13] Align PCA 3D group colors with 2D --- CHANGELOG.md | 1 + code/main.R | 14 +++++++++++++- tests/testthat/test-main.R | 9 +++++++++ 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d24f61..8005e4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Development version +- Fixed the 3D PCA capsule color mapping so group colors match the 2D PCA plot (#1, @phoman14). - Added tests for the plot pca 3D capsule Code Ocean panel and CLI contract (#1, @phoman14). - Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1, @phoman14). diff --git a/code/main.R b/code/main.R index 940db70..87aafa8 100644 --- a/code/main.R +++ b/code/main.R @@ -85,6 +85,18 @@ args <- parser$parse_args() # load multiOmicDataSet from data directory moo <- load_moo_from_data_dir() +color_values <- parse_optional_vector(args$color_values) +if (args$group_colname %in% colnames(moo@sample_meta)) { + group_values <- sort(unique(as.character( + moo@sample_meta[[args$group_colname]] + ))) + if (length(group_values) <= length(color_values)) { + color_values <- stats::setNames( + color_values[seq_along(group_values)], + group_values + ) + } +} # run MOSuite plot_pca( @@ -101,6 +113,6 @@ plot_pca( label_colname = args$label_colname, point_size = args$point_size, label_font_size = args$label_font_size, - color_values = parse_optional_vector(args$color_values), + color_values = color_values, plot_title = args$plot_title ) diff --git a/tests/testthat/test-main.R b/tests/testthat/test-main.R index 9ce5907..d452af6 100644 --- a/tests/testthat/test-main.R +++ b/tests/testthat/test-main.R @@ -48,6 +48,15 @@ test_that("3D PCA capsule keeps expected PCA parameter contract", { expect_equal(extract_panel_default(panel_lines, "plot_title"), "PCA 3D") }) +test_that("3D PCA names colors by group before plotting", { + main_text <- paste(read_repo_file("code", "main.R"), collapse = "\n") + + expect_match(main_text, "group_values <- sort\\(unique\\(as.character") + expect_match(main_text, "stats::setNames") + expect_match(main_text, "color_values\\[seq_along\\(group_values\\)\\]") + expect_match(main_text, "color_values = color_values") +}) + test_that("run wrapper prepares result directories and forwards CLI arguments", { run_lines <- read_repo_file("code", "run") run_text <- paste(run_lines, collapse = "\n") From 3d7d4b3d017a13e27d7045a9e732a16aa81125c1 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Tue, 30 Jun 2026 16:18:04 -0400 Subject: [PATCH 10/13] Revert "Align PCA 3D group colors with 2D" This reverts commit 5a35adf0111b1255053cb8bd20f1b52ec3cbde3c. --- CHANGELOG.md | 1 - code/main.R | 14 +------------- tests/testthat/test-main.R | 9 --------- 3 files changed, 1 insertion(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8005e4c..8d24f61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,6 @@ ## Development version -- Fixed the 3D PCA capsule color mapping so group colors match the 2D PCA plot (#1, @phoman14). - Added tests for the plot pca 3D capsule Code Ocean panel and CLI contract (#1, @phoman14). - Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1, @phoman14). diff --git a/code/main.R b/code/main.R index 87aafa8..940db70 100644 --- a/code/main.R +++ b/code/main.R @@ -85,18 +85,6 @@ args <- parser$parse_args() # load multiOmicDataSet from data directory moo <- load_moo_from_data_dir() -color_values <- parse_optional_vector(args$color_values) -if (args$group_colname %in% colnames(moo@sample_meta)) { - group_values <- sort(unique(as.character( - moo@sample_meta[[args$group_colname]] - ))) - if (length(group_values) <= length(color_values)) { - color_values <- stats::setNames( - color_values[seq_along(group_values)], - group_values - ) - } -} # run MOSuite plot_pca( @@ -113,6 +101,6 @@ plot_pca( label_colname = args$label_colname, point_size = args$point_size, label_font_size = args$label_font_size, - color_values = color_values, + color_values = parse_optional_vector(args$color_values), plot_title = args$plot_title ) diff --git a/tests/testthat/test-main.R b/tests/testthat/test-main.R index d452af6..9ce5907 100644 --- a/tests/testthat/test-main.R +++ b/tests/testthat/test-main.R @@ -48,15 +48,6 @@ test_that("3D PCA capsule keeps expected PCA parameter contract", { expect_equal(extract_panel_default(panel_lines, "plot_title"), "PCA 3D") }) -test_that("3D PCA names colors by group before plotting", { - main_text <- paste(read_repo_file("code", "main.R"), collapse = "\n") - - expect_match(main_text, "group_values <- sort\\(unique\\(as.character") - expect_match(main_text, "stats::setNames") - expect_match(main_text, "color_values\\[seq_along\\(group_values\\)\\]") - expect_match(main_text, "color_values = color_values") -}) - test_that("run wrapper prepares result directories and forwards CLI arguments", { run_lines <- read_repo_file("code", "run") run_text <- paste(run_lines, collapse = "\n") From 717b0c08f6004d63c48a2a0f916d61f79496cf30 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Thu, 2 Jul 2026 13:23:11 -0400 Subject: [PATCH 11/13] Document PCA 3D color fallback behavior Update color_values help text to describe the MOSuite default palette, supplied-color precedence, generated extra colors, and random fallback behavior. --- .codeocean/app-panel.json | 3 ++- code/main.R | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.codeocean/app-panel.json b/.codeocean/app-panel.json index eea2542..0c25463 100644 --- a/.codeocean/app-panel.json +++ b/.codeocean/app-panel.json @@ -138,7 +138,8 @@ "category": "FvI4Z2eb9sjL47Jt", "name": "Color values", "param_name": "color_values", - "description": "Comma-separated color values for groups", + "description": "Comma-separated group colors. Defaults to the MOSuite palette.", + "help_text": "Use color names or hex codes. Supplied colors are used first; if there are more groups than colors, additional colors are generated from the MOSuite palette, with random colors only if that palette is too short.", "type": "text", "value_type": "string", "default_value": "#5954d6,#e1562c,#b80058,#00c6f8,#d163e6,#00a76c,#ff9287,#008cf9,#006e00,#796880,#FFA500,#878500" diff --git a/code/main.R b/code/main.R index 940db70..0d68c59 100644 --- a/code/main.R +++ b/code/main.R @@ -72,7 +72,7 @@ parser$add_argument( "--color_values", type = "character", default = "#5954d6,#e1562c,#b80058,#00c6f8,#d163e6,#00a76c,#ff9287,#008cf9,#006e00,#796880,#FFA500,#878500", - help = "Comma-separated color values" + help = "Comma-separated group colors. Defaults to the MOSuite palette; supplied colors are used first and extra group colors are generated when needed." ) parser$add_argument( "--plot_title", From 517921bb383ffb652a0f04721ef42d3040b1b0cf Mon Sep 17 00:00:00 2001 From: phoman14 Date: Thu, 2 Jul 2026 14:52:12 -0400 Subject: [PATCH 12/13] Align PCA point size default --- code/main.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/main.R b/code/main.R index 0d68c59..8831391 100644 --- a/code/main.R +++ b/code/main.R @@ -72,7 +72,7 @@ parser$add_argument( "--color_values", type = "character", default = "#5954d6,#e1562c,#b80058,#00c6f8,#d163e6,#00a76c,#ff9287,#008cf9,#006e00,#796880,#FFA500,#878500", - help = "Comma-separated group colors. Defaults to the MOSuite palette; supplied colors are used first and extra group colors are generated when needed." + help = "Comma-separated group colors. Defaults to the MOSuite palette. Extra group colors are generated when needed." ) parser$add_argument( "--plot_title", From 0b0607de4f9235d31968845553ea7b583c7f3b84 Mon Sep 17 00:00:00 2001 From: phoman14 Date: Thu, 2 Jul 2026 15:49:31 -0400 Subject: [PATCH 13/13] docs: update PCA default changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d24f61..053213a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Development version +- Align the PCA color and point size defaults with MOSuite package defaults. +- Document that color palettes fall back to random colors only when too few colors are provided. - Added tests for the plot pca 3D capsule Code Ocean panel and CLI contract (#1, @phoman14). - Improved the Code Ocean parameter UI for the plot pca 3D capsule (#1, @phoman14).