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 low counts

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

- [Code Ocean Capsule](https://poc-nci.codeocean.io/capsule/2922767/tree)
- [MOSuite R package docs](https://ccbr.github.io/MOSuite/)
112 changes: 83 additions & 29 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,38 +12,93 @@ setup_capsule_environment()
# parse CLI arguments
parser <- ArgumentParser()

parser$add_argument("--count_type", type="character", default="clean")
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("--group_colname", type="character", default="Group", help="Column name for sample groups")
parser$add_argument("--label_colname", type="character", default=NULL, help="Column name for sample labels")
parser$add_argument("--minimum_count_value_to_be_considered_nonzero", type="integer", default=8, help="Minimum count threshold")
parser$add_argument("--minimum_number_of_samples_with_nonzero_counts_in_total", type="integer", default=7, help="Minimum samples with nonzero counts")
parser$add_argument("--minimum_number_of_samples_with_nonzero_counts_in_a_group", type="integer", default=3, help="Minimum samples per group with nonzero counts")
parser$add_argument("--use_cpm_counts_to_filter", type="logical", default=TRUE, help="Transform to CPM before filtering")
parser$add_argument("--use_group_based_filtering", type="logical", default=FALSE, help="Use group-based filtering")
parser$add_argument("--plot_corr_matrix_heatmap", type="logical", default=TRUE, help="Plot correlation heatmap")
parser$add_argument("--interactive_plots", type="logical", default=FALSE, help="Create interactive plots with plotly")
parser$add_argument("--count_type", type = "character", default = "clean")
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(
"--group_colname",
type = "character",
default = "Group",
help = "Column name for sample groups"
)
parser$add_argument(
"--label_colname",
type = "character",
default = NULL,
help = "Column name for sample labels"
)
parser$add_argument(
"--minimum_count_value_to_be_considered_nonzero",
type = "integer",
default = 8,
help = "Minimum count threshold"
)
parser$add_argument(
"--minimum_number_of_samples_with_nonzero_counts_in_total",
type = "integer",
default = 7,
help = "Minimum samples with nonzero counts"
)
parser$add_argument(
"--minimum_number_of_samples_with_nonzero_counts_in_a_group",
type = "integer",
default = 3,
help = "Minimum samples per group with nonzero counts"
)
parser$add_argument(
"--use_cpm_counts_to_filter",
type = "logical",
default = TRUE,
help = "Transform to CPM before filtering"
)
parser$add_argument(
"--use_group_based_filtering",
type = "logical",
default = FALSE,
help = "Use group-based filtering"
)
parser$add_argument(
"--plot_corr_matrix_heatmap",
type = "logical",
default = TRUE,
help = "Plot correlation heatmap"
)
parser$add_argument(
"--interactive_plots",
type = "logical",
default = FALSE,
help = "Create interactive plots with plotly"
)

args <- parser$parse_args()

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

# run MOSuite
moo |>
filter_counts(
count_type = args$count_type,
feature_id_colname = args$feature_id_colname,
sample_id_colname = args$sample_id_colname,
group_colname = args$group_colname,
label_colname = args$label_colname,
minimum_count_value_to_be_considered_nonzero = args$minimum_count_value_to_be_considered_nonzero,
minimum_number_of_samples_with_nonzero_counts_in_total = args$minimum_number_of_samples_with_nonzero_counts_in_total,
minimum_number_of_samples_with_nonzero_counts_in_a_group = args$minimum_number_of_samples_with_nonzero_counts_in_a_group,
use_cpm_counts_to_filter = args$use_cpm_counts_to_filter,
use_group_based_filtering = args$use_group_based_filtering,
plot_corr_matrix_heatmap = args$plot_corr_matrix_heatmap,
interactive_plots = args$interactive_plots
) |>
write_rds(file.path(getOption("moo_plots_dir"), "..", "moo", "moo.rds"))
moo |>
filter_counts(
count_type = args$count_type,
feature_id_colname = args$feature_id_colname,
sample_id_colname = args$sample_id_colname,
group_colname = args$group_colname,
label_colname = args$label_colname,
minimum_count_value_to_be_considered_nonzero = args$minimum_count_value_to_be_considered_nonzero,
minimum_number_of_samples_with_nonzero_counts_in_total = args$minimum_number_of_samples_with_nonzero_counts_in_total,
minimum_number_of_samples_with_nonzero_counts_in_a_group = args$minimum_number_of_samples_with_nonzero_counts_in_a_group,
use_cpm_counts_to_filter = args$use_cpm_counts_to_filter,
use_group_based_filtering = args$use_group_based_filtering,
plot_corr_matrix_heatmap = args$plot_corr_matrix_heatmap,
interactive_plots = args$interactive_plots
) |>
write_rds(file.path(getOption("moo_plots_dir"), "..", "moo", "moo-filt.rds"))
Binary file added tests/data/moo-clean.rds
Binary file not shown.
45 changes: 45 additions & 0 deletions tests/test-setup.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#!/usr/bin/env Rscript

# Simple test to verify the test setup and data exists
cat("Testing basic test setup...\n")

# Get the current working directory during test execution
cwd <- getwd()
cat("Current directory:", cwd, "\n")

# Calculate repo root the same way the test does in tests/testthat/test-main.R
# When running from tests/testthat, dirname(getwd()) goes to tests/
repo_root_test_calculation <- normalizePath(file.path(dirname(cwd), ".."))
cat(
"Calculated repo_root (test calculation):",
repo_root_test_calculation,
"\n"
)

# From script running in tests directory:
# When this script is in tests/ directory, repo_root should be dirname(getwd())
repo_root_script <- normalizePath(dirname(cwd))
cat("Calculated repo_root (script location):", repo_root_script, "\n")

# Check if test data exists using test calculation
test_data_file <- file.path(repo_root_script, "data", "moo-batch.rds")
cat("\nLooking for test data at:", test_data_file, "\n")
cat("Test data exists:", file.exists(test_data_file), "\n")

# Check code files
code_main <- file.path(repo_root_script, "..", "code", "main.R")
code_run <- file.path(repo_root_script, "..", "code", "run")
cat("code/main.R exists:", file.exists(code_main), "\n")
cat("code/run exists:", file.exists(code_run), "\n")

# Try to load the MOO object
if (file.exists(test_data_file)) {
cat("\nTrying to load MOO object...\n")
library(readr)
moo <- readr::read_rds(test_data_file)
cat("MOO object loaded successfully!\n")
cat("MOO class:", class(moo), "\n")
if (hasSlot(moo, "counts")) {
cat("MOO columns in counts:", names(moo@counts), "\n")
}
}
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)
136 changes: 136 additions & 0 deletions tests/testthat/test-main.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
test_that("code/run executes successfully with default CLI arguments", {
# Create temporary workspace
workspace <- tempfile("mosuite_filter_counts_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-clean.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",
"--count_type=clean",
"--minimum_count_value_to_be_considered_nonzero=8",
"--minimum_number_of_samples_with_nonzero_counts_in_total=7",
"--minimum_number_of_samples_with_nonzero_counts_in_a_group=3",
"--use_cpm_counts_to_filter=TRUE",
"--use_group_based_filtering=FALSE",
"--plot_corr_matrix_heatmap=FALSE"
)
)

# 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-filt.rds")),
info = "Output file moo-filt.rds should be created"
)

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

test_that("code/run executes with custom CLI arguments", {
# Create temporary workspace
workspace <- tempfile("mosuite_filter_counts_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-clean.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",
"--count_type=clean",
"--minimum_count_value_to_be_considered_nonzero=5",
"--minimum_number_of_samples_with_nonzero_counts_in_total=3",
"--use_cpm_counts_to_filter=FALSE",
"--plot_corr_matrix_heatmap=FALSE"
)
)

# 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-filt.rds")),
info = "Output file moo-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-filt.rds"))
expect_true(
S7::S7_inherits(moo, MOSuite::multiOmicDataSet),
info = "Output should be an S7 multiOmicDataSet object"
)
})