Skip to content
Open
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
6 changes: 6 additions & 0 deletions R/ModulePerturbation.R
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ TFPerturbation <- function(
wgcna_name = NULL
){

perturbation_name <- .sanitize_perturbation_name(perturbation_name)

# set as active assay if wgcna_name is not given
if(is.null(wgcna_name)){ wgcna_name <- seurat_obj@misc$active_wgcna }

Expand Down Expand Up @@ -362,6 +364,8 @@ ModulePerturbation <- function(
wgcna_name = NULL
){

perturbation_name <- .sanitize_perturbation_name(perturbation_name)

# set as active assay if wgcna_name is not given
if(is.null(wgcna_name)){wgcna_name <- seurat_obj@misc$active_wgcna}

Expand Down Expand Up @@ -710,6 +714,8 @@ CustomPerturbation <- function(
wgcna_name = NULL
){

perturbation_name <- .sanitize_perturbation_name(perturbation_name)

if(is.null(wgcna_name)){ wgcna_name <- seurat_obj@misc$active_wgcna }

# check assay
Expand Down
3 changes: 2 additions & 1 deletion R/PerturbationTransitions.R
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ PerturbationTransitions <- function(
paste(names(seurat_obj@assays), collapse = ', ')))
}

perturbation_name <- .resolve_perturbation_assay_name(seurat_obj, perturbation_name)

# check perturbation assay exists
if(!(perturbation_name %in% names(seurat_obj@assays))){
stop(paste0("Perturbation assay '", perturbation_name, "' not found in seurat_obj@assays. ",
Expand Down Expand Up @@ -145,4 +147,3 @@ PerturbationTransitions <- function(
colDeltaCor_velocyto <- function(e, d, nthreads = 1L) {
.Call('_velocyto_R_colDeltaCor', PACKAGE = 'velocyto.R', e, d, nthreads)
}

36 changes: 35 additions & 1 deletion R/Utilities.R
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,40 @@ PerturbationLog2FC <- function(
return(plot_df)
}

#' @keywords internal
#' @noRd
.sanitize_perturbation_name <- function(perturbation_name) {
if(!is.character(perturbation_name) || length(perturbation_name) != 1 ||
is.na(perturbation_name) || !nzchar(perturbation_name)){
stop("perturbation_name must be a non-empty character string.")
}

safe_name <- make.names(perturbation_name)
if(!identical(safe_name, perturbation_name)){
warning(paste0(
"perturbation_name '", perturbation_name, "' is not a valid Seurat assay name. ",
"Using '", safe_name, "' instead."
), call. = FALSE)
}

safe_name
}

#' @keywords internal
#' @noRd
.resolve_perturbation_assay_name <- function(seurat_obj, perturbation_name) {
if(perturbation_name %in% names(seurat_obj@assays)){
return(perturbation_name)
}

safe_name <- make.names(perturbation_name)
if(safe_name %in% names(seurat_obj@assays)){
return(safe_name)
}

perturbation_name
}

#' Check for Signal Saturation After Network Propagation
#'
#' After running \code{ApplyPropagation}, checks whether the propagated
Expand Down Expand Up @@ -272,4 +306,4 @@ CheckSignalDecay <- function(
}

invisible(result)
}
}
45 changes: 45 additions & 0 deletions tests/testthat/test-perturbation-name-sanitization.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
test_that("perturbation names are converted to valid Seurat assay names", {
examples <- data.frame(
input = c(
"HuMicA-M1_down",
"module 1_up",
"M-1/down",
"1module_down",
"red_up"
),
expected = c(
"HuMicA.M1_down",
"module.1_up",
"M.1.down",
"X1module_down",
"red_up"
),
stringsAsFactors = FALSE
)

for(i in seq_len(nrow(examples))){
input <- examples$input[i]
expected <- examples$expected[i]

if(identical(input, expected)){
expect_silent(
safe_name <- .sanitize_perturbation_name(input)
)
} else {
expect_warning(
safe_name <- .sanitize_perturbation_name(input),
paste0("Using '", expected, "' instead"),
fixed = TRUE
)
}

expect_identical(safe_name, expected)
}
})

test_that("perturbation names must be a single non-empty string", {
expect_error(.sanitize_perturbation_name(character()), "non-empty character string")
expect_error(.sanitize_perturbation_name(c("red_up", "blue_up")), "non-empty character string")
expect_error(.sanitize_perturbation_name(""), "non-empty character string")
expect_error(.sanitize_perturbation_name(NA_character_), "non-empty character string")
})