R/msearch.R
27774aee
 #' Classify Spatially Variable Genes to interpretable fitting classes
8c680e71
 #'
27774aee
 #' Compare model fits with different models, using the
8c680e71
 #' [**SpatialDE**](https://github.com/Teichlab/SpatialDE) Python package.
 #'
d16afa63
 #' @param x A numeric `matrix` of counts where genes are rows and cells are columns.
 #'
 #'    Alternatively, a \linkS4class{SpatialExperiment} object.
8c680e71
 #'
 #' @param ... For the generic, arguments to pass to specific methods.
 #' @param de_results `data.frame` resulting from [run()] or [spatialDE()].
d16afa63
 #' @param coordinates A `data.frame` with sample coordinates. Each row is a
 #'   sample, the columns with coordinates should be named 'x' and 'y'.
 #'
 #'   For the *SpatialExperiment* method, coordinates are taken from
 #'   `spatialCoords(x)`.
 #'
8c680e71
 #' @param qval_thresh `numeric` scalar, specifying the q-value significance
 #'   threshold to filter `de_results`. Only rows in `de_results` with
 #'   `qval < qval_thresh` will be kept. To disable, set `qval_thresh = NULL`.
d16afa63
 #' @param assay_type A `character` string specifying the assay from `x` to use
 #'   as input. Defaults to `"counts"`.
8c680e71
 #' @param verbose A `logical` controlling the display of a progress bar from the
 #'   Python package.
 #'
 #' @return `data.frame` of model_search results.
 #'
 #' @examples
6b99d290
 #' ## Mock up a SpatialExperiment object wit 400 cells and 3 genes
8c680e71
 #' set.seed(42)
6b99d290
 #' spe <- mockSVG(size = 20, tot_genes = 3, de_genes = 1, return_SPE = TRUE)
8c680e71
 #'
 #' ## Run spatialDE with S4 integration
 #' de_results <- spatialDE(spe)
27774aee
 #'
d16afa63
 #' ## Run model search
27774aee
 #' model_search <- modelSearch(spe, de_results = de_results,
 #'     qval_thresh = NULL, verbose = FALSE
 #' )
 #'
8c680e71
 #' @seealso
 #' The individual steps performed by this function: [stabilize()],
 #' [regress_out()] and [model_search()].
 #'
 #' @references
 #' Svensson, V., Teichmann, S. & Stegle, O. SpatialDE: identification of
 #' spatially variable genes. Nat Methods 15, 343–346 (2018).
 #' \url{https://doi.org/10.1038/nmeth.4636}
 #'
 #' [**SpatialDE 1.1.3**](https://pypi.org/project/SpatialDE/1.1.3/): the version
 #' of the Python package used under the hood.
 #'
f9403c31
 #' @author Davide Corso, Milan Malfait, Lambda Moses
27774aee
 #' @name modelSearch
8c680e71
 NULL
 
 #' @importFrom Matrix colSums
d16afa63
 #' @importFrom checkmate assert_data_frame assert_number assert_flag
 .modelSearch <- function(x, de_results, coordinates,
                          qval_thresh = 0.05, verbose = FALSE) {
     assert_data_frame(de_results, all.missing = FALSE)
     assert_number(qval_thresh, null.ok = TRUE)
     assert_flag(verbose)
 
     ## Filter de_results
     if (!is.null(qval_thresh)) {
         de_results <- .filter_de_results(
             de_results = de_results, qval_thresh = qval_thresh
         )
     }
 
     sample_info <- data.frame(coordinates, total_counts = colSums(x))
0262f312
     
     .run_model_search(x = x, sample_info = sample_info, de_results = de_results,
d16afa63
         verbose = verbose
     )
8c680e71
 }
 
d16afa63
 .run_model_search <- function(x, sample_info, de_results, verbose = FALSE) {
0262f312
     proc <- basiliskStart(spatialDE_env, testload="scipy.optimize")
     
     # Normalization
     ## Stabilize
     .naiveDE_stabilize(proc, x)
     stabilized <- basiliskRun(proc, function(store) {
         as.matrix(store$stabilized)
     }, persist=TRUE)
     
     ## Regress_out
     .naiveDE_regress_out(proc, stabilized, sample_info)
     regressed <- basiliskRun(proc, function(store) {
         as.matrix(store$regressed)
     }, persist=TRUE)
27774aee
 
d16afa63
     coordinates <- sample_info[, c("x", "y")]
353bd6f2
     .importPyModule(proc, !verbose)
0262f312
     .spatialDE_model_search(proc, regressed, coordinates, de_results)
     
     out <- basiliskRun(proc, function(store) {
         store$model_search
     }, persist=TRUE)
     
     out
8c680e71
 }
 
 #' @import methods
 #' @export
27774aee
 #' @rdname modelSearch
ca8f68a9
 setGeneric("modelSearch",
     function(x, de_results, ...) standardGeneric("modelSearch"),
     signature = "x"
 )
8c680e71
 
d16afa63
 #' @export
 #' @rdname modelSearch
 setMethod("modelSearch", "matrix", .modelSearch)
 
8c680e71
 #' @export
27774aee
 #' @rdname modelSearch
8c680e71
 #' @importFrom SummarizedExperiment assay
27774aee
 #' @importFrom SpatialExperiment spatialCoords spatialCoordsNames<-
8c680e71
 setMethod("modelSearch", "SpatialExperiment",
d16afa63
     function(x, de_results, assay_type = "counts",
              qval_thresh = 0.05, verbose = FALSE) {
27774aee
 
d16afa63
         ## Rename spatialCoords columns to "x", "y"
         spatialCoordsNames(x) <- c("x", "y")
         coordinates <- as.data.frame(spatialCoords(x))
27774aee
 
d16afa63
         .modelSearch(
             x = assay(x, assay_type), de_results = de_results,
             coordinates = coordinates, qval_thresh = qval_thresh,
             verbose = verbose
         )
8c680e71
     }
 )