--- title: "nnSVG tutorial" author: - name: Lukas M. Weber affiliation: &id1 "Johns Hopkins Bloomberg School of Public Health, Baltimore, MD, USA" - name: Stephanie C. Hicks affiliation: &id1 package: nnSVG output: BiocStyle::html_document vignette: > %\VignetteIndexEntry{nnSVG tutorial} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- # Introduction `nnSVG` is a method for scalable identification of spatially variable genes (SVGs) in spatially-resolved transcriptomics data. The `nnSVG` method is based on nearest-neighbor Gaussian processes ([Datta et al., 2016](https://www.tandfonline.com/doi/full/10.1080/01621459.2015.1044091), [Finley et al., 2019](https://www.tandfonline.com/doi/full/10.1080/10618600.2018.1537924)) and uses the BRISC algorithm ([Saha and Datta, 2018](https://onlinelibrary.wiley.com/doi/full/10.1002/sta4.184)) for model fitting and parameter estimation. `nnSVG` allows identification and ranking of SVGs with flexible length scales across a tissue slide or within spatial domains defined by covariates. The method scales linearly with the number of spatial locations and can be applied to datasets containing thousands or more spatial locations. `nnSVG` is implemented as an R package within the Bioconductor framework, and is available from [Bioconductor](https://bioconductor.org/packages/nnSVG). More details describing the method are available in our preprint, available from [bioRxiv](https://www.biorxiv.org/content/10.1101/2022.05.16.492124v1). # Installation The following code will install the latest release version of the `nnSVG` package from Bioconductor. Additional details are shown on the [Bioconductor](https://bioconductor.org/packages/nnSVG) page. ```{r, eval=FALSE} if (!requireNamespace("BiocManager", quietly = TRUE)) { install.packages("BiocManager") } BiocManager::install("nnSVG") ``` The latest development version can also be installed from the `devel` version of Bioconductor or from [GitHub](https://github.com/lmweber/nnSVG). # Input data format In the examples below, we assume the input data are provided as a [SpatialExperiment](https://bioconductor.org/packages/SpatialExperiment) Bioconductor object. In this case, the outputs are stored in the `rowData` of the `SpatialExperiment` object. However, the inputs can also be provided as a numeric matrix of normalized and transformed counts (e.g. log-transformed normalized counts) and a numeric matrix of spatial coordinates. To provide the inputs as numeric matrices, please install the development version of the package from [GitHub](https://github.com/lmweber/nnSVG) or the `devel` version of Bioconductor (which will become the new Bioconductor release version in October 2022). # Tutorial ## Run nnSVG Here we show a short example demonstrating how to run `nnSVG`. For faster runtime in this example, we subsample the dataset and run `nnSVG` on only a small number of genes. For a full analysis, the subsampling step can be skipped. ```{r, message=FALSE} library(SpatialExperiment) library(STexampleData) library(scran) library(nnSVG) library(ggplot2) ``` ```{r} # load example dataset from STexampleData package spe <- Visium_humanDLPFC() dim(spe) ``` ```{r} # preprocessing steps # keep only spots over tissue spe <- spe[, colData(spe)$in_tissue == 1] dim(spe) # skip spot-level quality control, since this has been performed previously # on this dataset # filter low-expressed and mitochondrial genes # using default filtering parameters spe <- filter_genes(spe) # calculate log-transformed normalized counts using scran package # (alternatively could calculate deviance residuals using scry package) set.seed(123) qclus <- quickCluster(spe) spe <- computeSumFactors(spe, cluster = qclus) spe <- logNormCounts(spe) assayNames(spe) ``` ```{r} # select small set of random genes and several known SVGs for # faster runtime in this example set.seed(123) ix_random <- sample(seq_len(nrow(spe)), 10) known_genes <- c("MOBP", "PCP4", "SNAP25", "HBB", "IGKC", "NPY") ix_known <- which(rowData(spe)$gene_name %in% known_genes) ix <- c(ix_known, ix_random) spe <- spe[ix, ] dim(spe) ``` ```{r} # run nnSVG # set seed for reproducibility set.seed(123) # using a single thread in this example spe <- nnSVG(spe) # show results rowData(spe) ``` ## Investigate results The results are stored in the `rowData` of the `SpatialExperiment` object. The main results of interest are: - `LR_stat`: likelihood ratio (LR) statistics - `rank`: rank of top SVGs according to LR statistics - `pval`: p-values from asymptotic chi-squared distribution with 2 degrees of freedom - `padj`: p-values adjusted for multiple testing, which can be used to define a cutoff for statistically significant SVGs (e.g. `padj` <= 0.05) - `prop_sv`: effect size, defined as proportion of spatial variance out of total variance ```{r} # number of significant SVGs table(rowData(spe)$padj <= 0.05) ``` ```{r} # show results for top n SVGs rowData(spe)[order(rowData(spe)$rank)[1:10], ] ``` ```{r, fig.width=5, fig.height=5} # plot spatial expression of top-ranked SVG ix <- which(rowData(spe)$rank == 1) ix_name <- rowData(spe)$gene_name[ix] ix_name df <- as.data.frame( cbind(spatialCoords(spe), expr = counts(spe)[ix, ])) ggplot(df, aes(x = pxl_col_in_fullres, y = pxl_row_in_fullres, color = expr)) + geom_point(size = 0.8) + coord_fixed() + scale_y_reverse() + scale_color_gradient(low = "gray90", high = "blue", name = "counts") + ggtitle(ix_name) + theme_bw() + theme(panel.grid = element_blank(), axis.title = element_blank(), axis.text = element_blank(), axis.ticks = element_blank()) ``` # Session information ```{r} sessionInfo() ```