diff --git a/DESCRIPTION b/DESCRIPTION index ebf1bb9..b06e372 100755 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,14 +1,14 @@ Type: Package Package: SpaceMarkers Title: Spatial Interaction Markers -Version: 1.11.1 +Version: 1.1.2 Authors@R: c( person(given = "Atul", family = "Deshpande", email = "adeshpande@jhu.edu", role = c("aut", "cre"), comment = c(ORCID="0000-0001-5144-6924")), person(given = "Ludmila", family = "Danilova", email = "ldanilo1@jhmi.edu", role = "ctb"), - person(given = "Dimitrijs", family = "Lvovs", email = "dlvovs1@jh.edu", role = "ctb") + person(given = "Dmitrijs", family = "Lvovs", email = "dlvovs1@jh.edu", role = "ctb", comment = c(ORCID = "0009-0003-2152-6853")) ) -BugReports: https://github.com/atuldeshpande/SpaceMarkers/issues -URL: https://github.com/atuldeshpande/SpaceMarkers +BugReports: https://github.com/DeshpandeLab/SpaceMarkers/issues +URL: https://github.com/DeshpandeLab/SpaceMarkers Description: Spatial transcriptomic technologies have helped to resolve the connection between gene expression and the 2D orientation of tissues relative to each other. However, the limited single-cell resolution makes it difficult to highlight the most @@ -48,6 +48,8 @@ Suggests: testthat (>= 3.0.0), viridis, CoGAPS +Enhances: + BiocParallel VignetteBuilder: knitr Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index 851e0f0..a73c9b5 100755 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,6 +1,7 @@ # Generated by roxygen2: do not edit by hand export(getInteractingGenes) +export(getPairwiseInteractingGenes) export(getSpatialFeatures) export(getSpatialParameters) export(load10XCoords) diff --git a/NEWS.md b/NEWS.md index 4464440..98f78b7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,4 +1,9 @@ -# SpaceMarkers development version +# SpaceMarkers 1.1.2 + +* Added getPairwiseInteractingGenes which enables pairwise analysis of +interacting patterns + +# SpaceMarkers 1.1.1 * `getSpatialFeatures`: add default method to infer the object passed to it. diff --git a/R/find_genes_of_interest.R b/R/find_genes_of_interest.R index 496b1cf..e351b03 100644 --- a/R/find_genes_of_interest.R +++ b/R/find_genes_of_interest.R @@ -48,21 +48,15 @@ return(cbind(zVals,pvals)) #=================== #' find_genes_of_interest #' Identify genes associated with pattern interaction. - #' This function identifies genes exhibiting significantly higher values of #' testMat in the Interaction region of the two -#' patterns compared #' to regions with exclusive influence from either +#' patterns compared to regions with exclusive influence from either #' pattern. It uses Kruskal-Wallis test followed by #' posthoc analysis using Dunn's Test to identify the genes. #' #' @usage -#' find_genes_of_interest( -#' testMat, -#' goodGenes = NULL, -#' region, -#' fdr.level = 0.05, -#' analysis = c("enrichment", "overlap") -#' ) +#' find_genes_of_interest(testMat, goodGenes, region, fdr.level=0.05, +#' analysis=c("enrichment","overlap"),...) #' @param testMat A matrix of counts with cells as columns and genes as rows #' @param goodGenes A vector of user specified genes expected to interact #' a priori. The default for this is NULL as the function can find these genes @@ -72,18 +66,23 @@ return(cbind(zVals,pvals)) #' @param fdr.level False Discovery Rate. The default value is 0.05. #' @param analysis a character string that specifies the type of analysis to #' carry out, whether overlap or enrichment. -#' +#' @param ... Additional arguments to be passed to lower level functions #' @return a list of genes exhibiting significantly higher values of testMat in #' the Interaction region of the two #' patterns compared to regions with #' exclusive influence from either pattern. - - find_genes_of_interest<-function( testMat,goodGenes=NULL,region, fdr.level=0.05, - analysis=c("enrichment","overlap")) { + analysis=c("enrichment","overlap"),...) { + + # Default analysis = enrichment + if ("enrichment" %in% analysis) {analysis <- "enrichment"} + else if ("overlap" %in% analysis) {analysis <- "overlap"} + else stop("analysis must be either 'enrichment' or 'overlap'") + region <- factor(region) patnames <- levels(region)[which(levels(region)!="Interacting")] + pattern1 <- patnames[1] pattern2 <- patnames[2] if (!is.null(goodGenes)){ @@ -104,6 +103,12 @@ find_genes_of_interest<-function( qDunn$qvalues[ind,] <- qq$qvalue res_dunn_test <- cbind(res_dunn_test,qDunn$qvalues) colnames(res_dunn_test)[7:9] <- paste0(colnames(res_dunn_test)[7:9],".adj") + interactGenes <- buildInteractGenesdf(res_kruskal, + res_dunn_test,ind,fdr.level, pattern1,pattern2,analysis) + return(interactGenes) +} +buildInteractGenesdf <- function(res_kruskal,res_dunn_test,ind, + fdr.level=0.05,pattern1,pattern2,analysis) { interact_patt1 <- res_dunn_test[ind,"pval_1_Int.adj"]1) + + if (use_biocparallel) { + + # Determine the number of workers to use + if (is.null(workers)) { + workers <- BiocParallel::multicoreWorkers() # Use default + } else if (workers <= 0) { + stop("Invalid number of workers. # + Please provide a positive integer.") + } + + # Register parallel backend + bpparam <- BiocParallel::MulticoreParam(workers = workers) + + # Run the loop with BiocParallel + results <- BiocParallel::bplapply(input_list, function(args) { + # call getInteractingGenes for a pair + do.call(getInteractingGenes, c(list(data = data), + list(reconstruction=reconstruction), args, ...)) + }, BPPARAM = bpparam) # Use the specified parallel backend + } else { + # Use a regular for loop with input_list + results <- vector("list", length = length(input_list)) + + for (ii in seq(1,length(input_list))){ + results[[ii]] <- do.call(getInteractingGenes, c(list(data = data), + list(reconstruction=reconstruction), input_list[[ii]],...)) + } + } + for (ii in seq(1,length(results))) + results[[ii]]$patterns <- patternPairs[ii,] + names(results) <- apply(patternPairs,1,paste,collapse="_") + return(results) +} + +# Create a list of arguments for passing two patterns to getInteractingGenes +pairArgsList <- function(patternPair, argsParams) { + patcols <- c("x","y", "barcode",patternPair) + argList <- list( + spPatterns = argsParams$spPatterns[, patcols], + hotspots = argsParams$hotspots[, patcols], + optParams = argsParams$optParams[, patternPair], + refPattern = patternPair[1], + mode = argsParams$mode, + analysis = argsParams$analysis, + minOverlap = argsParams$minOverlap) + return(argList) +} + +getPatternPairs <- function(patternList, patternPairs) { + if (is.null(patternPairs)){ + message("patternPairs not provided. Calculating all + possible pairs.") + patternPairs <- t(utils::combn(patternList,2,simplify = TRUE)) + } else { + if (is.list(patternPairs)) { + if (!all(vapply(patternPairs,length, FUN.VALUE = 1)==2)) + stop("Each item in the patternPairs list + must be a vector of 2 patterns.") + patternPairs <- do.call(rbind, patternPairs) + } else if (is.matrix(patternPairs)) { + if (ncol(patternPairs) != 2) + stop("patternPairs matrix must have 2 columns.") + } else if(is.character(patternPairs)) { + if (length(patternPairs)!=2){ + stop("A single pair be a character vector of length 2.") + } else + patternPairs <- matrix(patternPairs, nrow=1) + } + else + stop("patternPairs must either be a 2-column matrix + or a list of vectors.") + + if (!all(patternPairs %in% patternList)) + stop("Following are not pattern names: ", + paste0(setdiff(patternPairs, patternList)," ")) + } + return(patternPairs) +} diff --git a/R/preprocessing.R b/R/preprocessing.R index 69c3923..4654748 100644 --- a/R/preprocessing.R +++ b/R/preprocessing.R @@ -115,7 +115,7 @@ load10XCoords <- function(visiumDir, resolution = "lowres", version = NULL){ } else if (version == "2.0") { has_header <- TRUE tissue_pos_name <- "tissue_positions.csv" - } + } spatial_dir <- paste0(visiumDir,'/spatial') scale_json <- dir(spatial_dir, pattern = "scalefactors_json.json",full.names = TRUE) @@ -167,8 +167,8 @@ getSpatialFeatures <- function(filePath, method = NULL, featureNames = "."){ method <- .inferMethod(spObject, method) spFun <- c("CoGAPS"=.getCogapsFeatures, - "BayesTME"=.getBTMEfeatures, - "Seurat"=.getSeuratFeatures) + "BayesTME"=.getBTMEfeatures, + "Seurat"=.getSeuratFeatures) spFeatures <- spFun[[method]](spObject) @@ -185,7 +185,7 @@ getSpatialFeatures <- function(filePath, method = NULL, featureNames = "."){ } } else if(!all(featureNames %in% dataNames)) { stop("Some of the features were not found:", - sprintf(" %s", setdiff(featureNames, dataNames))) + sprintf(" %s", setdiff(featureNames, dataNames))) } featureNames <- intersect(featureNames, dataNames) diff --git a/R/test-helper.R b/R/test-helper.R new file mode 100644 index 0000000..a2a8471 --- /dev/null +++ b/R/test-helper.R @@ -0,0 +1,21 @@ +# helper file for tests + +# create sample data for getPairwiseInteractingGenes +createSampleData <- function(...) { + data <- matrix(stats::rnorm(100), nrow = 10) + rownames(data) <- paste0("gene_", seq_len(10)) + colnames(data) <- paste0("spot_", seq_len(10)) + spPatterns <- as.data.frame(matrix(stats::rnorm(40), nrow = 10)) + optParams <- data.matrix(data.frame("pattern1" = c(.2,3), + "pattern2" = c(.2,3), + "pattern3" = c(.2,3), + "pattern4" = c(.2,3))) + rownames(optParams) <- c("sigmaOpt","threshOpt") + patnames <- colnames(spPatterns) <- + c("pattern1", "pattern2", "pattern3", "pattern4") + coords <- data.frame(x = stats::runif(10), y = stats::runif(10), + barcode = paste0("spot_",seq_len(10))) + spPatterns <- cbind(coords,spPatterns) + return(list(data = data, spPatterns = spPatterns, + patnames = patnames, optParams = optParams)) +} diff --git a/inst/CITATION b/inst/CITATION new file mode 100644 index 0000000..2763a0b --- /dev/null +++ b/inst/CITATION @@ -0,0 +1,14 @@ +bibentry( + bibtype = "Article", + title = "Uncovering the spatial landscape of molecular interactions within the tumor microenvironment through latent spaces", + volume = "14", + issn = "2405-4712", + url = "https://www.cell.com/cell-systems/abstract/S2405-4712(23)00080-7", + doi = "10.1016/j.cels.2023.03.004", + number = "4", + journal = "Cell Systems", + author = "Deshpande, Atul and Loth, Melanie and Sidiropoulos, Dimitrios N. and Zhang, Shuming and Yuan, Long and Bell, Alexander T. F. and Zhu, Qingfeng and Ho, Won Jin and Santa-Maria, Cesar and Gilkes, Daniele M. and Williams, Stephen R. and Uytingco, Cedric R. and Chew, Jennifer and Hartnett, Andrej and Bent, Zachary W. and Favorov, Alexander V. and Popel, Aleksander S. and Yarchoan, Mark and Kiemen, Ashley and Wu, Pei-Hsun and Fujikura, Kohei and Wirtz, Denis and Wood, Laura D. and Zheng, Lei and Jaffee, Elizabeth M. and Anders, Robert A. and Danilova, Ludmila and Stein-O’Brien, Genevieve and Kagohara, Luciane T. and Fertig, Elana J.", + month = "apr", + year = "2023", + pmid = "37080163" +) diff --git a/man/find_genes_of_interest.Rd b/man/find_genes_of_interest.Rd index 230b566..eaa387d 100644 --- a/man/find_genes_of_interest.Rd +++ b/man/find_genes_of_interest.Rd @@ -6,17 +6,12 @@ Identify genes associated with pattern interaction. This function identifies genes exhibiting significantly higher values of testMat in the Interaction region of the two -patterns compared #' to regions with exclusive influence from either +patterns compared to regions with exclusive influence from either pattern. It uses Kruskal-Wallis test followed by posthoc analysis using Dunn's Test to identify the genes.} \usage{ -find_genes_of_interest( - testMat, - goodGenes = NULL, - region, - fdr.level = 0.05, - analysis = c("enrichment", "overlap") -) +find_genes_of_interest(testMat, goodGenes, region, fdr.level=0.05, + analysis=c("enrichment","overlap"),...) } \arguments{ \item{testMat}{A matrix of counts with cells as columns and genes as rows} @@ -32,6 +27,8 @@ with the other patterns} \item{analysis}{a character string that specifies the type of analysis to carry out, whether overlap or enrichment.} + +\item{...}{Additional arguments to be passed to lower level functions} } \value{ a list of genes exhibiting significantly higher values of testMat in @@ -43,7 +40,7 @@ find_genes_of_interest Identify genes associated with pattern interaction. This function identifies genes exhibiting significantly higher values of testMat in the Interaction region of the two -patterns compared #' to regions with exclusive influence from either +patterns compared to regions with exclusive influence from either pattern. It uses Kruskal-Wallis test followed by posthoc analysis using Dunn's Test to identify the genes. } diff --git a/man/getInteractingGenes.Rd b/man/getInteractingGenes.Rd index 4bfc83b..e5982d4 100644 --- a/man/getInteractingGenes.Rd +++ b/man/getInteractingGenes.Rd @@ -5,17 +5,19 @@ \title{getInteractingGenes Calculate Interaction Regions and Associated Genes This function calculates statistically significant genes using a -non-parametric Kruskal-Wallis test for genes in any one region of influence -and a post hoc Dunn's test is used for analysis of genes between regions.} +non-parametric Kruskal-Wallis test for genes in any one region +of influence and a post hoc Dunn's test is used for analysis of +genes between regions.} \usage{ getInteractingGenes( data, spPatterns, refPattern = "Pattern_1", - mode = c("residual", "DE"), + mode = c("DE", "residual"), optParams = NULL, reconstruction = NULL, hotspots = NULL, + analysis = c("enrichment", "overlap"), minOverlap = 50, ... ) @@ -34,7 +36,8 @@ to study. The default value is "Pattern_1".} \item{mode}{SpaceMarkers mode of operation. Possible values are "residual" (the default) or "DE".} -\item{optParams}{a matrix with dimensions 2 X N, where N is the number +\item{optParams}{a matrix with dimensions 2 X N, +where N is the number of patterns with optimal parameters for outlier detection calculated from function getSpatialParameters(). The first row contains the kernel width sigmaOpt for each @@ -50,6 +53,12 @@ spaces. Required for "residual" mode.} to the 'refPattern'. The default is NULL which indicates that all patterns would be compared to the 'refPattern'.} +\item{analysis}{a character string that specifies the type of downstream +analysis to be performed. Possible values are "enrichment" (default) +and "overlap". In enrichment mode, all genes are returned, ranked by +the SpaceMarkers metric. In overlap mode, only the genes which are +significantly overexpressed in the interaction region are returned.} + \item{minOverlap}{a number that specifies the minimum overlap between genes in two patterns to be considered for the statistical tests. The default is 50.} @@ -66,8 +75,9 @@ regions of influence for any two of patterns (the hotspots object). getInteractingGenes Calculate Interaction Regions and Associated Genes This function calculates statistically significant genes using a -non-parametric Kruskal-Wallis test for genes in any one region of influence -and a post hoc Dunn's test is used for analysis of genes between regions. +non-parametric Kruskal-Wallis test for genes in any one region +of influence and a post hoc Dunn's test is used for analysis of +genes between regions. } \examples{ library(SpaceMarkers) @@ -99,7 +109,8 @@ untar(basename(sp_url)) spCoords <- load10XCoords(visiumDir = ".", version = "1.0") rownames(spCoords) <- spCoords$barcode spCoords <- spCoords[barcodes,] -spPatterns <- cbind(spCoords,slot(cogaps_result,"sampleFactors")[barcodes,]) +spPatterns <- cbind(spCoords,slot(cogaps_result, +"sampleFactors")[barcodes,]) data("curated_genes") spPatterns<-spPatterns[c("barcode","y","x","Pattern_1","Pattern_5")] counts_matrix <- counts_matrix[curated_genes,] @@ -120,3 +131,8 @@ files <- list.files(".")[grepl(basename(counts_url),list.files("."))] unlink(files) } +\seealso{ +Other getIntGenes: +\code{\link{getPairwiseInteractingGenes}()} +} +\concept{getIntGenes} diff --git a/man/getPairwiseInteractingGenes.Rd b/man/getPairwiseInteractingGenes.Rd new file mode 100644 index 0000000..8db6300 --- /dev/null +++ b/man/getPairwiseInteractingGenes.Rd @@ -0,0 +1,139 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/getInteractingGenes.R +\name{getPairwiseInteractingGenes} +\alias{getPairwiseInteractingGenes} +\title{getPairwiseInteractingGenes} +\usage{ +getPairwiseInteractingGenes( + data, + spPatterns, + mode = c("DE", "residual"), + optParams = NULL, + reconstruction = NULL, + hotspots = NULL, + minOverlap = 50, + analysis = c("enrichment", "overlap"), + patternPairs = NULL, + ..., + workers = NULL +) +} +\arguments{ +\item{data}{original spatial data matrix.} + +\item{spPatterns}{A data frame that contains the spatial coordinates +for each cell type. The column names must include 'x' and 'y' as well as a +set of numbered columns named 'Pattern_1.....N'.} + +\item{mode}{SpaceMarkers mode of operation. Possible values are +"residual" (the default) or "DE".} + +\item{optParams}{a matrix with dimensions 2 X N, +where N is the number +of patterns with optimal parameters for outlier +detection calculated from function getSpatialParameters(). The first row +contains the kernel width sigmaOpt for each +pattern, and the second row is the threshOpt (outlier threshold) for each +pattern. Users can also input their +preferred param values. +The default value is NULL.} + +\item{reconstruction}{reconstruction of the data matrix from latent +spaces. Required for "residual" mode.} + +\item{hotspots}{a vector that specifies the patterns to compare +to the 'refPattern'. The default is NULL which indicates that all patterns +would be compared to the 'refPattern'.} + +\item{minOverlap}{a number that specifies the minimum overlap between +genes in two patterns to be considered for the statistical tests. +The default is 50.} + +\item{analysis}{a character string that specifies the type of downstream +analysis to be performed. Possible values are "enrichment" (default) +and "overlap". In enrichment mode, all genes are returned, ranked by +the SpaceMarkers metric. In overlap mode, only the genes which are +significantly overexpressed in the interaction region are returned.} + +\item{patternPairs}{A matrix of pattern pairs to be analyzed. Default is} + +\item{...}{Arguments passed to methods} + +\item{workers}{(optional) Number of workers to +be used for parallel processing.} +} +\value{ +a list of data frames for each pattern with 1) names of the patterns +(patterns object) 2) data frame with the hotspots of influence for the +two patterns (the hotspots object). 3) data frame with the genes +associated with the interaction between the two patterns +(interacting genes object, empty if insufficient interaction). +} +\description{ +Performs pairwise analysis to find genes associated with +spatial interaction between pairs of spatially varying patterns. +} +\details{ +================ +} +\examples{ +library(SpaceMarkers) +#Visium data links +urls <- read.csv(system.file("extdata","visium_data.txt", +package="SpaceMarkers",mustWork = TRUE)) +counts_url <- urls[["visium_url"]][1] +sp_url <- urls[["visium_url"]][2] +#Remove present Directories if any +unlink(basename(sp_url)) +unlink("spatial", recursive = TRUE) +files <- list.files(".")[grepl(basename(counts_url),list.files("."))] +unlink(files) +download.file(counts_url,basename(counts_url), mode = "wb") +counts_matrix<-load10XExpr(visiumDir=".", +h5filename = basename(counts_url)) +#Obtaining CoGAPS Patterns +cogaps_result <- readRDS(system.file("extdata","CoGAPS_result.rds", +package="SpaceMarkers",mustWork = TRUE)) +features <- intersect(rownames(counts_matrix),rownames( + slot(cogaps_result,"featureLoadings"))) +barcodes <- intersect(colnames(counts_matrix),rownames( + slot(cogaps_result,"sampleFactors"))) +counts_matrix <- counts_matrix[features,barcodes] +cogaps_matrix <- slot(cogaps_result,"featureLoadings")[features,]\%*\% + t(slot(cogaps_result,"sampleFactors")[barcodes,]) +#Obtaining Spatial Coordinates +download.file(sp_url, basename(sp_url), mode = "wb") +untar(basename(sp_url)) +spCoords <- load10XCoords(visiumDir = ".", version = "1.0") +rownames(spCoords) <- spCoords$barcode +spCoords <- spCoords[barcodes,] +spPatterns <- cbind(spCoords, +slot(cogaps_result,"sampleFactors")[barcodes,]) +data("curated_genes") +spPatterns<-spPatterns[c("barcode","y","x","Pattern_1", +"Pattern_3","Pattern_5")] +counts_matrix <- counts_matrix[curated_genes,] +cogaps_matrix <- cogaps_matrix[curated_genes, ] +optParams <- matrix(c(6, 2, 6, 2, 6, 2), nrow = 2) +rownames(optParams) <- c("sigmaOpt","threshOpt") +colnames(optParams) <- c("Pattern_1","Pattern_3","Pattern_5") +SpaceMarkersMode <- "DE" +patternPairs <- matrix(c("Pattern_1", "Pattern_1", + "Pattern_3", "Pattern_5"), nrow=2) +SpaceMarkers_test <- getPairwiseInteractingGenes( + data=counts_matrix,reconstruction=NULL, + optParams = optParams, + spPatterns = spPatterns, + mode="DE",analysis="enrichment", patternPairs=patternPairs) +#Remove present Directories if any +unlink(basename(sp_url)) +unlink("spatial", recursive = TRUE) +files <- list.files(".")[grepl(basename(counts_url),list.files("."))] +unlink(files) + +} +\seealso{ +Other getIntGenes: +\code{\link{getInteractingGenes}()} +} +\concept{getIntGenes} diff --git a/tests/testthat/test-getPairwiseInteractingGenes.R b/tests/testthat/test-getPairwiseInteractingGenes.R new file mode 100644 index 0000000..edcef9b --- /dev/null +++ b/tests/testthat/test-getPairwiseInteractingGenes.R @@ -0,0 +1,124 @@ +# 1. Test with no 'patternPairs' provided +test_that("No patternPairs - computes all pairs", { + # Create sample data (adjust to match your actual data structure) + args <- createSampleData() + # Call the function + + suppressMessages( + result <- getPairwiseInteractingGenes(data=args$data, + spPatterns=args$spPatterns, + optParams=args$optParams, minOverlap = 0) + ) + patnames <- setdiff(colnames(args$spPatterns), c("x", "y", "barcode")) + # Check the number of results (should be 1 since there are 2 patterns) + expect_equal(length(result), choose(length(patnames), 2)) + patcombs <- t(utils::combn(patnames, 2)) + patcombs <- apply(patcombs, 1, function(x) paste(x, collapse = "_")) + # Check the names of the results (should be "pattern1_pattern2") + expect_equal(names(result), patcombs) +}) + +# 2. Test with a matrix of 'patternPairs' +test_that("Matrix patternPairs - specific pairs", { + # Create sample data + args <- createSampleData() + # Define specific pattern pairs + patternPairs <- rbind(c("pattern1", "pattern2"), c("pattern1", "pattern3")) + + # Call the function + suppressMessages( + result <- getPairwiseInteractingGenes(data=args$data, + spPatterns=args$spPatterns, + optParams=args$optParams, + patternPairs = patternPairs, minOverlap = 0) + ) + # Check the number of results (should be 1) + expect_equal(length(result), 2) + + # Check the names of the results + expect_equal(names(result), c("pattern1_pattern2", "pattern1_pattern3")) +}) + +# 3. Test with a list of 'patternPairs' +test_that("List patternPairs - specific pairs", { + # Create sample data + args <- createSampleData() + # Define specific pattern pairs as a list + patternPairs <- list(c("pattern1", "pattern2")) + + # Call the function + suppressMessages( + result <- getPairwiseInteractingGenes(data=args$data, + spPatterns=args$spPatterns, + optParams=args$optParams, + patternPairs = patternPairs, minOverlap = 0) + ) + # Check the number of results (should be 1) + expect_equal(length(result), 1) + + # Check the names of the results + expect_equal(names(result), "pattern1_pattern2") +}) + +# 4. Test with invalid 'patternPairs' +test_that("Invalid patternPairs - throws error", { + # Create sample data + args <- createSampleData() + + # Define invalid pattern pairs + patternPairs <- matrix(c("pattern1", "invalid_pattern"), ncol = 2) + + # Expect an error + expect_error(result <- getPairwiseInteractingGenes(data=args$data, + spPatterns=args$spPatterns, + optParams=args$optParams, + patternPairs = patternPairs, minOverlap = 0), "not pattern names") +}) + +# 5. Test without BiocParallel +test_that("No BiocParallel - sequential execution", { + # Mock 'requireNamespace' to always return FALSE + myRequire <- function(...) FALSE + local_mocked_bindings(requireNamespace = myRequire, .package = "base") + # Create sample data + args <- createSampleData() + # Define specific pattern pairs + patternPairs <- rbind(c("pattern1", "pattern2"), + c("pattern1", "pattern3")) + + # Call the function + suppressMessages( + result <- getPairwiseInteractingGenes(data=args$data, + spPatterns=args$spPatterns, + optParams=args$optParams, + patternPairs = patternPairs, minOverlap = 0) + ) + # Check the number of results (should be 1) + expect_equal(length(result), 2) + + # Check the names of the results + expect_equal(names(result), c("pattern1_pattern2", + "pattern1_pattern3")) +}) + +#6. Test for single pair of patterns +test_that("Single pair of patterns", { + # Create sample data + args <- createSampleData() + # Define specific pattern pairs + patternPairs <- c("pattern1", "pattern2") + + # Call the function + suppressMessages( + result <- getPairwiseInteractingGenes(data=args$data, + spPatterns=args$spPatterns, + optParams=args$optParams, + patternPairs = patternPairs, minOverlap = 0) + ) + + # Check the number of results (should be 1) + expect_equal(length(result), 1) + + # Check the names of the results + expect_equal(names(result), "pattern1_pattern2") +})