Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@

Code Ocean capsule: MOSuite - filter differential expression analysis results

[![tests](https://github.com/NIDAP-Community/MOSuite-filter-diff/actions/workflows/tests.yml/badge.svg)](https://github.com/NIDAP-Community/MOSuite-filter-diff/actions/workflows/tests.yml)

- [Code Ocean Capsule](https://poc-nci.codeocean.io/capsule/8221739/tree) | [Latest Release](https://poc-nci.codeocean.io/capsule/0936928/tree/latest)
- [MOSuite R package docs](https://ccbr.github.io/MOSuite/)
212 changes: 163 additions & 49 deletions code/main.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/usr/bin/env Rscript
rlang::global_entrace()
library(argparse)
library(glue)
library(MOSuite)
Expand All @@ -13,58 +12,173 @@ setup_capsule_environment()
# parse CLI arguments
parser <- ArgumentParser()

parser$add_argument("--feature_id_colname", type="character", default=NULL, help="Column name for feature IDs")
parser$add_argument("--significance_column", type="character", default="adjpval", help="Column name for significance")
parser$add_argument("--significance_cutoff", type="double", default=0.05, help="Significance cutoff threshold")
parser$add_argument("--change_column", type="character", default="logFC", help="Column name for change")
parser$add_argument("--change_cutoff", type="double", default=1, help="Change cutoff threshold")
parser$add_argument("--filtering_mode", type="character", default="any", help="Filter mode: any or all")
parser$add_argument("--include_estimates", type="character", default="FC,logFC,tstat,pval,adjpval", help="Comma-separated list of estimates to include")
parser$add_argument("--round_estimates", type="logical", default=TRUE, help="Round estimates")
parser$add_argument("--rounding_decimal_for_percent_cells", type="integer", default=0, help="Decimal places for percent labels")
parser$add_argument("--contrast_filter", type="character", default="none", help="Filter contrasts: keep, remove, or none")
parser$add_argument("--contrasts", type="character", default="", help="Comma-separated list of contrasts")
parser$add_argument("--groups", type="character", default="", help="Comma-separated list of groups")
parser$add_argument("--groups_filter", type="character", default="none", help="Filter groups: keep, remove, or none")
parser$add_argument("--label_font_size", type="double", default=6, help="Font size for labels")
parser$add_argument("--label_distance", type="double", default=1, help="Distance of labels from bars")
parser$add_argument("--y_axis_expansion", type="double", default=0.08, help="Y-axis expansion")
parser$add_argument("--fill_colors", type="character", default="steelblue1,whitesmoke", help="Comma-separated fill colors")
parser$add_argument("--pie_chart_in_3d", type="logical", default=TRUE, help="Draw pie charts in 3D")
parser$add_argument("--bar_width", type="double", default=0.4, help="Bar width")
parser$add_argument("--draw_bar_border", type="logical", default=TRUE, help="Draw bar borders")
parser$add_argument("--plot_type", type="character", default="bar", help="Plot type: bar or pie")
parser$add_argument("--plot_titles_fontsize", type="integer", default=12, help="Font size for plot titles")
parser$add_argument(
"--feature_id_colname",
type = "character",
default = NULL,
help = "Column name for feature IDs"
)
parser$add_argument(
"--significance_column",
type = "character",
default = "adjpval",
help = "Column name for significance"
)
parser$add_argument(
"--significance_cutoff",
type = "double",
default = 0.05,
help = "Significance cutoff threshold"
)
parser$add_argument(
"--change_column",
type = "character",
default = "logFC",
help = "Column name for change"
)
parser$add_argument(
"--change_cutoff",
type = "double",
default = 1,
help = "Change cutoff threshold"
)
parser$add_argument(
"--filtering_mode",
type = "character",
default = "any",
help = "Filter mode: any or all"
)
parser$add_argument(
"--include_estimates",
type = "character",
default = "FC,logFC,tstat,pval,adjpval",
help = "Comma-separated list of estimates to include"
)
parser$add_argument(
"--round_estimates",
type = "logical",
default = TRUE,
help = "Round estimates"
)
parser$add_argument(
"--rounding_decimal_for_percent_cells",
type = "integer",
default = 0,
help = "Decimal places for percent labels"
)
parser$add_argument(
"--contrast_filter",
type = "character",
default = "none",
help = "Filter contrasts: keep, remove, or none"
)
parser$add_argument(
"--contrasts",
type = "character",
default = "",
help = "Comma-separated list of contrasts"
)
parser$add_argument(
"--groups",
type = "character",
default = "",
help = "Comma-separated list of groups"
)
parser$add_argument(
"--groups_filter",
type = "character",
default = "none",
help = "Filter groups: keep, remove, or none"
)
parser$add_argument(
"--label_font_size",
type = "double",
default = 6,
help = "Font size for labels"
)
parser$add_argument(
"--label_distance",
type = "double",
default = 1,
help = "Distance of labels from bars"
)
parser$add_argument(
"--y_axis_expansion",
type = "double",
default = 0.08,
help = "Y-axis expansion"
)
parser$add_argument(
"--fill_colors",
type = "character",
default = "steelblue1,whitesmoke",
help = "Comma-separated fill colors"
)
parser$add_argument(
"--pie_chart_in_3d",
type = "logical",
default = TRUE,
help = "Draw pie charts in 3D"
)
parser$add_argument(
"--bar_width",
type = "double",
default = 0.4,
help = "Bar width"
)
parser$add_argument(
"--draw_bar_border",
type = "logical",
default = TRUE,
help = "Draw bar borders"
)
parser$add_argument(
"--plot_type",
type = "character",
default = "bar",
help = "Plot type: bar or pie"
)
parser$add_argument(
"--plot_titles_fontsize",
type = "integer",
default = 12,
help = "Font size for plot titles"
)

args <- parser$parse_args()

# load multiOmicDataSet from data directory
moo <- load_moo_from_data_dir()

# run MOSuite
moo |>
filter_diff(
feature_id_colname = args$feature_id_colname,
significance_column = args$significance_column,
significance_cutoff = args$significance_cutoff,
change_column = args$change_column,
change_cutoff = args$change_cutoff,
filtering_mode = args$filtering_mode,
include_estimates = parse_optional_vector(args$include_estimates),
round_estimates = args$round_estimates,
rounding_decimal_for_percent_cells = args$rounding_decimal_for_percent_cells,
contrast_filter = args$contrast_filter,
contrasts = parse_optional_vector(args$contrasts),
groups = parse_optional_vector(args$groups),
groups_filter = args$groups_filter,
label_font_size = args$label_font_size,
label_distance = args$label_distance,
y_axis_expansion = args$y_axis_expansion,
fill_colors = parse_optional_vector(args$fill_colors),
pie_chart_in_3d = args$pie_chart_in_3d,
bar_width = args$bar_width,
draw_bar_border = args$draw_bar_border,
plot_type = args$plot_type,
plot_titles_fontsize = args$plot_titles_fontsize
) |>
write_rds(file.path(getOption("moo_plots_dir"), "..", "moo", "moo.rds"))
moo |>
filter_diff(
feature_id_colname = args$feature_id_colname,
significance_column = args$significance_column,
significance_cutoff = args$significance_cutoff,
change_column = args$change_column,
change_cutoff = args$change_cutoff,
filtering_mode = args$filtering_mode,
include_estimates = parse_optional_vector(args$include_estimates),
round_estimates = args$round_estimates,
rounding_decimal_for_percent_cells = args$rounding_decimal_for_percent_cells,
contrast_filter = args$contrast_filter,
contrasts = parse_optional_vector(args$contrasts),
groups = parse_optional_vector(args$groups),
groups_filter = args$groups_filter,
label_font_size = args$label_font_size,
label_distance = args$label_distance,
y_axis_expansion = args$y_axis_expansion,
fill_colors = parse_optional_vector(args$fill_colors),
pie_chart_in_3d = args$pie_chart_in_3d,
bar_width = args$bar_width,
draw_bar_border = args$draw_bar_border,
plot_type = args$plot_type,
plot_titles_fontsize = args$plot_titles_fontsize
) |>
write_rds(file.path(
getOption("moo_plots_dir"),
"..",
"moo",
"moo-diff-filt.rds"
))
Binary file added tests/data/moo-diff.rds
Binary file not shown.
2 changes: 2 additions & 0 deletions tests/testthat.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
library(testthat)
test_dir(file.path('tests', 'testthat'), stop_on_failure = TRUE)
148 changes: 148 additions & 0 deletions tests/testthat/test-main.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
test_that("code/run executes successfully with default CLI arguments", {
# Create temporary workspace
workspace <- tempfile("mosuite_filter_diff_test_")
dir.create(workspace)
on.exit(unlink(workspace, recursive = TRUE), add = TRUE)

# Set up directory structure
code_dir <- file.path(workspace, "code")
data_dir <- file.path(workspace, "data")
results_dir <- file.path(code_dir, "..", "results")
dir.create(code_dir)
dir.create(data_dir)
dir.create(results_dir)

# Get test data from package tests directory
repo_root <- normalizePath(file.path(dirname(getwd()), ".."))
test_data_file <- file.path(repo_root, "tests", "data", "moo-diff.rds")

expect_true(
file.exists(test_data_file),
info = paste("Test data file should exist at", test_data_file)
)
file.copy(test_data_file, file.path(data_dir, "moo.rds"))

# Copy main.R and run script to workspace
file.copy(
file.path(repo_root, "code", "main.R"),
file.path(code_dir, "main.R")
)
file.copy(
file.path(repo_root, "code", "run"),
file.path(code_dir, "run")
)

# Run the script from code directory
old_wd <- getwd()
setwd(code_dir)
on.exit(setwd(old_wd), add = TRUE)

# Execute run script with default CLI arguments
exit_code <- system2(
"bash",
args = c(
"run",
"--significance_column=adjpval",
"--significance_cutoff=0.05",
"--change_column=logFC",
"--change_cutoff=1",
"--filtering_mode=any"
)
)

# Check for successful execution
expect_equal(exit_code, 0, info = "run script should execute without error")
expect_true(
file.exists(file.path(results_dir, "moo", "moo-diff-filt.rds")),
info = "Output file moo-diff-filt.rds should be created"
)

# Validate output is a valid MOO object
moo <- readr::read_rds(file.path(results_dir, "moo", "moo-diff-filt.rds"))
expect_true(
S7::S7_inherits(moo, MOSuite::multiOmicDataSet),
info = "Output should be an S7 multiOmicDataSet object"
)

# Validate diff results exist
expect_true(
"diff" %in% names(moo@analyses),
info = "Output should have diff results in moo@analyses"
)
})

test_that("code/run executes with custom CLI arguments", {
# Create temporary workspace
workspace <- tempfile("mosuite_filter_diff_custom_test_")
dir.create(workspace)
on.exit(unlink(workspace, recursive = TRUE), add = TRUE)

# Set up directory structure
code_dir <- file.path(workspace, "code")
data_dir <- file.path(workspace, "data")
results_dir <- file.path(code_dir, "..", "results")
dir.create(code_dir)
dir.create(data_dir)
dir.create(results_dir)

# Get test data from package tests directory
repo_root <- normalizePath(file.path(dirname(getwd()), ".."))
test_data_file <- file.path(repo_root, "tests", "data", "moo-diff.rds")

# Copy test data to workspace
file.copy(test_data_file, file.path(data_dir, "moo.rds"))

# Copy main.R and run script to workspace
file.copy(
file.path(repo_root, "code", "main.R"),
file.path(code_dir, "main.R")
)
file.copy(
file.path(repo_root, "code", "run"),
file.path(code_dir, "run")
)

# Run the script from code directory
old_wd <- getwd()
setwd(code_dir)
on.exit(setwd(old_wd), add = TRUE)

# Execute run script with custom CLI arguments
exit_code <- system2(
"bash",
args = c(
"run",
"--significance_column=pval",
"--significance_cutoff=0.01",
"--change_column=logFC",
"--change_cutoff=2",
"--filtering_mode=all",
"--round_estimates=TRUE",
"--plot_type=bar"
)
)

# Check for successful execution
expect_equal(
exit_code,
0,
info = "run script with custom args should execute without error"
)
expect_true(
file.exists(file.path(results_dir, "moo", "moo-diff-filt.rds")),
info = "Output file moo-diff-filt.rds should be created with custom args"
)

# Validate output is a valid MOO object
moo <- readr::read_rds(file.path(results_dir, "moo", "moo-diff-filt.rds"))
expect_true(
S7::S7_inherits(moo, MOSuite::multiOmicDataSet),
info = "Output should be an S7 multiOmicDataSet object"
)

# Validate diff results exist
expect_true(
"diff" %in% names(moo@analyses),
info = "Output should have diff results in moo@analyses"
)
})