├── .Rbuildignore ├── .github ├── .gitignore └── workflows │ └── check-standard.yml ├── .gitignore ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── Banksy-package.R ├── cluster.R ├── computation.R ├── data.R ├── misc.R ├── reduction.R └── zzz.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── data ├── hippocampus.rda └── rings.rda ├── docs ├── 404.html ├── LICENSE-text.html ├── articles │ ├── batch-correction.html │ ├── domain-segment.html │ ├── figures │ │ ├── batch-correction-spatial-1.png │ │ ├── batch-correction-umap-1.png │ │ ├── domain-segment-spatial-1.png │ │ ├── multi-sample-spatial-1.png │ │ ├── multi-sample-umap-1.png │ │ └── parameter-selection-spatial-1.png │ ├── index.html │ ├── multi-sample.html │ └── parameter-selection.html ├── authors.html ├── bootstrap-toc.css ├── bootstrap-toc.js ├── docsearch.css ├── docsearch.js ├── index.html ├── link.svg ├── news │ └── index.html ├── pkgdown.css ├── pkgdown.js ├── pkgdown.yml ├── reference │ ├── Banksy-package.html │ ├── Rplot001.png │ ├── clusterBanksy.html │ ├── clusterNames.html │ ├── compareClusters.html │ ├── computeBanksy.html │ ├── connectClusters.html │ ├── figures │ │ ├── README-unnamed-chunk-12-1.png │ │ ├── README-unnamed-chunk-13-1.png │ │ ├── README-unnamed-chunk-14-1.png │ │ └── README-unnamed-chunk-15-1.png │ ├── getBanksyMatrix.html │ ├── hippocampus.html │ ├── index.html │ ├── rings.html │ ├── runBanksyPCA.html │ ├── runBanksyUMAP.html │ ├── simulateDataset-1.png │ ├── simulateDataset.html │ └── smoothLabels.html └── sitemap.xml ├── inst ├── CITATION ├── extdata │ └── STARmap.rds └── script │ └── rings.R ├── man ├── Banksy-package.Rd ├── clusterBanksy.Rd ├── clusterNames.Rd ├── compareClusters.Rd ├── computeBanksy.Rd ├── connectClusters.Rd ├── figures │ ├── README-unnamed-chunk-12-1.png │ ├── README-unnamed-chunk-13-1.png │ ├── README-unnamed-chunk-14-1.png │ └── README-unnamed-chunk-15-1.png ├── getBanksyMatrix.Rd ├── hippocampus.Rd ├── rings.Rd ├── runBanksyPCA.Rd ├── runBanksyUMAP.Rd ├── simulateDataset.Rd └── smoothLabels.Rd ├── tests ├── testthat.R └── testthat │ ├── test-cluster.R │ ├── test-computation.R │ ├── test-misc.R │ └── test-reduction.R └── vignettes ├── .gitignore ├── batch-correction.Rmd ├── domain-segment.Rmd ├── figures ├── batch-correction-spatial-1.png ├── batch-correction-umap-1.png ├── domain-segment-spatial-1.png ├── multi-sample-spatial-1.png ├── multi-sample-umap-1.png └── parameter-selection-spatial-1.png ├── multi-sample.Rmd └── parameter-selection.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^Banksy\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^LICENSE\.md$ 4 | ^README\.Rmd$ 5 | ^_pkgdown\.yml$ 6 | ^docs$ 7 | ^pkgdown$ 8 | ^\.github$ 9 | ^codecov\.yml$ 10 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/check-standard.yml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: windows-latest, r: 'release'} 22 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 23 | - {os: ubuntu-latest, r: 'release'} 24 | - {os: ubuntu-latest, r: 'oldrel-1'} 25 | 26 | env: 27 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 28 | R_KEEP_PKG_SOURCE: yes 29 | 30 | steps: 31 | - uses: actions/checkout@v3 32 | 33 | - uses: r-lib/actions/setup-pandoc@v2 34 | 35 | - uses: r-lib/actions/setup-r@v2 36 | with: 37 | r-version: ${{ matrix.config.r }} 38 | http-user-agent: ${{ matrix.config.http-user-agent }} 39 | use-public-rspm: true 40 | 41 | - uses: r-lib/actions/setup-r-dependencies@v2 42 | with: 43 | extra-packages: any::rcmdcheck 44 | needs: check 45 | 46 | - uses: r-lib/actions/check-r-package@v2 47 | with: 48 | upload-snapshots: true -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | *.Rproj 3 | .Rhistory 4 | data/Human_DLPFC_Visium_processedData_sce_scran_spatialLIBD.Rdata 5 | .DS_Store 6 | inst/.DS_Store -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: Banksy 2 | Title: Spatial transcriptomic clustering 3 | Version: 1.3.0 4 | Authors@R: c( 5 | person(given = "Vipul", 6 | family = "Singhal", 7 | role = c("aut")), 8 | person(given = "Joseph", 9 | family = "Lee", 10 | role = c("aut", "cre"), 11 | email = "joseph.lee@u.nus.edu", 12 | comment = c(ORCID="0000-0002-4983-4714")) 13 | ) 14 | Description: Banksy is an R package that incorporates spatial information to 15 | cluster cells in a feature space (e.g. gene expression). To incorporate 16 | spatial information, BANKSY computes the mean neighborhood expression and 17 | azimuthal Gabor filters that capture gene expression gradients. These 18 | features are combined with the cell's own expression to embed cells in a 19 | neighbor-augmented product space which can then be clustered, allowing for 20 | accurate and spatially-aware cell typing and tissue domain segmentation. 21 | Depends: 22 | R (>= 4.4.0) 23 | Imports: 24 | aricode, 25 | data.table, 26 | dbscan, 27 | SpatialExperiment, 28 | SingleCellExperiment, 29 | SummarizedExperiment, 30 | S4Vectors, 31 | stats, 32 | matrixStats, 33 | mclust, 34 | igraph, 35 | irlba, 36 | leidenAlg (>= 1.1.0), 37 | utils, 38 | uwot, 39 | RcppHungarian 40 | License: file LICENSE 41 | Encoding: UTF-8 42 | URL: https://github.com/prabhakarlab/Banksy 43 | BugReports: https://github.com/prabhakarlab/Banksy/issues 44 | RoxygenNote: 7.3.1 45 | Suggests: 46 | knitr, 47 | rmarkdown, 48 | pals, 49 | scuttle, 50 | scater, 51 | scran, 52 | cowplot, 53 | ggplot2, 54 | testthat (>= 3.0.0), 55 | harmony, 56 | Seurat, 57 | ExperimentHub, 58 | spatialLIBD, 59 | BiocStyle 60 | VignetteBuilder: knitr 61 | Config/testthat/edition: 3 62 | biocViews: 63 | Clustering, 64 | Spatial, 65 | SingleCell, 66 | GeneExpression, 67 | DimensionReduction 68 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | USER LICENSE for the software suite BANKSY 3 | 4 | TLDR (see below for details). 5 | Academic usage: MIT License 6 | Commercial Usage: Restrictions applicable, see below. 7 | 8 | Authorship and Copyright (c) 9 | 2022; Vipul Singhal, Joseph Lee 10 | 11 | References of associated scientific publications 12 | 1) Singhal, V., Chou, N., Lee, J. et al. BANKSY unifies cell typing and tissue domain segmentation for scalable spatial omics data analysis. Nat Genet 56, 431–441 (2024). https://doi.org/10.1038/s41588-024-01664-3 13 | 14 | *** 15 | 16 | Vipul Singhal 17 | vipul_singhal@gis.a-star.edu.sg 18 | Genome Institute of Singapore, 60 Biopolis Street, Singapore 138672 19 | 20 | Joseph Lee 21 | joseph.lee@u.nus.edu 22 | Genome Institute of Singapore, 60 Biopolis Street, Singapore 138672 23 | 24 | *** 25 | 26 | License conditions 27 | 28 | 1. Definitions 29 | 30 | “Author” refers to the person(s) that hold the authors’ rights or to an organization that has been entitled by them or their employer during the work on the software suite to protect the respective rights and to issue user licenses. 31 | 32 | “Software” includes all program or database files as well as associated documentation files together with this license document. 33 | 34 | This license refers to the software suite in the title of this document with all its author’s versions. This includes the newest one and any preceding version - be it in “source code form” (the preferred form of the work for making modifications to it) or “object form” (any compiled/executable version of it). This license covers both the whole software as well as any part of it. It is applicable to the standalone versions of this software as well as its incorporation as integral part into other software packages. 35 | 36 | “User” is the licensee of this software. 37 | 38 | 2. Copyright notice 39 | 40 | All rights are reserved, whether the whole or part of the software is concerned. The software may not be used or distributed without specific, prior written permission of the author beyond the exceptions described in this license. 41 | 42 | This especially concerns respecting the authors’ rights. The user will always refer to the authors, their publications and this software package when communicating about this software, any of its modifications or about results obtained with this software. 43 | 44 | The copyright messages (if any) will not be modified or suppressed. The software package will always remain associated with this license agreement. 45 | 46 | 3. Academic (non-commercial) usage: MIT License 47 | 48 | Copyright (c) <2022> 49 | 50 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 51 | 52 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 53 | 54 | 4. Commercial usage 55 | 56 | The usage of this software in commercial activities is not allowed without a prior written commercial licence agreement issued by the author. 57 | 58 | Any software package that contains this software or parts of it can only be commercialized with a license agreement issued by the author. 59 | 60 | 5. Warranty and liability 61 | 62 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 63 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING OUT OF OR IN CONNECTION WITH THE USE, PERFORMANCE OF THIS SOFTWARE OR ANY OTHER DEALINGS WITH IT, WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY. 64 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | export(clusterBanksy) 4 | export(clusterNames) 5 | export(compareClusters) 6 | export(computeBanksy) 7 | export(connectClusters) 8 | export(getBanksyMatrix) 9 | export(runBanksyPCA) 10 | export(runBanksyUMAP) 11 | export(simulateDataset) 12 | export(smoothLabels) 13 | importFrom(RcppHungarian,HungarianSolver) 14 | importFrom(S4Vectors,"metadata<-") 15 | importFrom(S4Vectors,metadata) 16 | importFrom(SingleCellExperiment,"reducedDim<-") 17 | importFrom(SingleCellExperiment,reducedDim) 18 | importFrom(SingleCellExperiment,reducedDimNames) 19 | importFrom(SpatialExperiment,SpatialExperiment) 20 | importFrom(SpatialExperiment,spatialCoords) 21 | importFrom(SummarizedExperiment,"assay<-") 22 | importFrom(SummarizedExperiment,"colData<-") 23 | importFrom(SummarizedExperiment,assay) 24 | importFrom(SummarizedExperiment,assayNames) 25 | importFrom(SummarizedExperiment,assays) 26 | importFrom(SummarizedExperiment,colData) 27 | importFrom(aricode,AMI) 28 | importFrom(aricode,ARI) 29 | importFrom(aricode,MARI) 30 | importFrom(aricode,MARIraw) 31 | importFrom(aricode,NID) 32 | importFrom(aricode,NMI) 33 | importFrom(aricode,NVI) 34 | importFrom(aricode,RI) 35 | importFrom(data.table,.N) 36 | importFrom(data.table,.SD) 37 | importFrom(data.table,`:=`) 38 | importFrom(data.table,data.table) 39 | importFrom(data.table,rbindlist) 40 | importFrom(data.table,setDT) 41 | importFrom(data.table,setnames) 42 | importFrom(data.table,setorder) 43 | importFrom(dbscan,kNN) 44 | importFrom(dbscan,sNN) 45 | importFrom(igraph,as.undirected) 46 | importFrom(igraph,cluster_louvain) 47 | importFrom(igraph,graph_from_data_frame) 48 | importFrom(irlba,prcomp_irlba) 49 | importFrom(leidenAlg,leiden.community) 50 | importFrom(matrixStats,rowSds) 51 | importFrom(mclust,Mclust) 52 | importFrom(mclust,mclustBIC) 53 | importFrom(stats,dnorm) 54 | importFrom(stats,kmeans) 55 | importFrom(stats,median) 56 | importFrom(stats,rpois) 57 | importFrom(stats,runif) 58 | importFrom(utils,combn) 59 | importFrom(utils,packageVersion) 60 | importFrom(utils,tail) 61 | importFrom(uwot,umap) 62 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | 2 | # Version 0.99.8 3 | 4 | + Add feature scaling options for PCA and UMAP 5 | 6 | # Version 0.99.7 7 | 8 | + SCE/SPE-compatible 9 | 10 | # Version 0.1.6 11 | 12 | + Fix compatibility with SeuratWrappers 13 | 14 | # Version 0.1.5 15 | 16 | + Implemented SmoothLabels for k-nearest neighbors cluster label smoothing 17 | + Parallel clustering for Leiden graph-based clustering 18 | + Version depedency on leidenAlg (>= 1.1.0) for compatibility with igraph (>= 1.5.0) 19 | + Seed setting for clustering 20 | + Neighborhood sampling for computing neighborhood feature matrices. See arguments 21 | `sample_size`, `sample_renorm` and `seed` in function ComputeBanksy 22 | 23 | # Version 0.1.4 24 | 25 | + Implemented Azimuthal Gabor filters in ComputeBanksy, with the number of 26 | harmonics determined by the `M` argument. To obtain similar results as version 27 | 0.1.3, use `M=0` 28 | + RunPCA and RunUMAP renamed to RunBanksyPCA and RunBanksyUMAP respectively to 29 | avoid namespace collisions with other packages 30 | + Changed some function argument names (e.g. `spatialMode` to `spatial_mode`) 31 | 32 | # Version 0.1.3 33 | 34 | + Interoperability with SingleCellExperiment with asBanksyObject 35 | + Passing Bioc and R CMD checks 36 | 37 | # Version 0.1.2 38 | 39 | + BanksyObject: dimensionality reduction slot name changed to reduction 40 | + RunPCA and RunUMAP 41 | + Plotting is generalised (plotReduction instead of plotUMAP / plotPCA) 42 | + ConnectClusters improved and returns BanksyObject 43 | + ARI computation and plotting 44 | 45 | # Version 0.0.9 46 | 47 | + Legacy version 48 | -------------------------------------------------------------------------------- /R/Banksy-package.R: -------------------------------------------------------------------------------- 1 | #' 2 | #' The Banksy package 3 | #' 4 | #' Banksy is a library and R package for network analysis. 5 | #' 6 | #' @rdname Banksy-package 7 | #' @name Banksy-package 8 | #' @keywords internal 9 | #' @aliases Banksy-package Banksy 10 | #' @docType package 11 | #' 12 | #' @section Description: 13 | #' Banksy is an R package that incorporates spatial information to cluster 14 | #' cells in a feature space (e.g. gene expression). To incorporate spatial 15 | #' information, BANKSY computes the mean neighborhood expression and azimuthal 16 | #' Gabor filters that capture gene expression gradients. These features are 17 | #' combined with the cell's own expression to embed cells in a 18 | #' neighbor-augmented product space which can then be clustered, allowing for 19 | #' accurate and spatially-aware cell typing and tissue domain segmentation. 20 | #' 21 | #' @section Details: 22 | #' For a quick start to the package, please refer to the GitHub page at 23 | #' \url{https://github.com/prabhakarlab/Banksy}. For in-depth guides to package 24 | #' functionality and use cases, refer to the package webpage at 25 | #' \url{https://prabhakarlab.github.io/Banksy}. 26 | #' 27 | "_PACKAGE" -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' Mouse Hippocampus VeraFISH data 2 | #' 3 | #' This dataset comprises VeraFISH profiling of cells in the mouse hippocampus. 4 | #' Gene expression and cell centroids for 10,944 cells and 129 genes in 2 5 | #' spatial dimensions are provided. For details on how this dataset was 6 | #' generated, refer to Supplementary Information section 2.2 of our 7 | #' \href{https://www.biorxiv.org/content/10.1101/2022.04.14.488259v1.supplementary-material}{preprint}. 8 | #' 9 | #' @format A list with 2 entries: 10 | #' \describe{ 11 | #' \item{expression}{(matrix) gene expression matrix} 12 | #' \item{locations}{(data.frame) cell centroids in 2D} 13 | #' } 14 | #' 15 | #' @usage data(hippocampus) 16 | #' 17 | #' @return List with expression and locations 18 | #' 19 | "hippocampus" 20 | 21 | #' An unrealistic simulation of spatially-resolved omics data. 22 | #' 23 | #' This dataset comprises gene expression and spatial coordinates for 50 genes 24 | #' and 308 cells from 4 clusters (\code{rings$clusters}). See \code{system.file('scripts/rings.R', package='Banksy')} on how this dataset was generated. 25 | #' 26 | #' @format A SpatialExperiment object. 27 | #' 28 | #' @usage data(rings) 29 | #' 30 | #' @return A SpatialExperiment object 31 | #' 32 | "rings" 33 | -------------------------------------------------------------------------------- /R/misc.R: -------------------------------------------------------------------------------- 1 | #' Simulate an unrealistic spatial omics dataset. 2 | #' 3 | #' @details 4 | #' This function generates an unrealistic spatial omics dataset based on a 5 | #' user-specified number of cells and genes. The number of clusters is defined 6 | #' by \code{n_rings}, while counts follow a Poisson distribution with a 7 | #' user-specified rate \code{rate}. The simulation is set up such that the 8 | #' number of cells in each cluster is uniformly distributed; as such, the final 9 | #' number of cells is approximately equal to the user-specified number of cells. 10 | #' 11 | #' 12 | #' @param n_cells An integer scalar specifying the approximate number of cells. 13 | #' @param n_genes An integer scalar specifying the number of genes. 14 | #' @param n_rings An integer scalar specifying the number of spatial rings. 15 | #' @param rate A numeric scalar specifying the Poisson rate parameter for 16 | #' simulating counts. 17 | #' 18 | #' @importFrom stats rpois runif 19 | #' @importFrom SpatialExperiment SpatialExperiment 20 | #' 21 | #' @return A SpatialExperiment object. 22 | #' 23 | #' @export 24 | #' 25 | #' @examples 26 | #' set.seed(2023) 27 | #' rings <- simulateDataset(n_cells = 5e3, n_genes = 50, n_rings = 8) 28 | #' rings 29 | #' table(rings$cluster) 30 | #' df <- cbind.data.frame( 31 | #' SummarizedExperiment::colData(rings), 32 | #' SpatialExperiment::spatialCoords(rings)) 33 | #' library(ggplot2) 34 | #' ggplot(df, aes(x=x, y=y, col=cluster)) + geom_point() + theme_classic() 35 | #' 36 | simulateDataset <- function(n_cells = 300, 37 | n_genes = 30, 38 | n_rings = 3, 39 | rate = 10) { 40 | # Generate spatial locations 41 | n_cells <- ceiling(n_cells / (0.25 * pi)) 42 | x <- runif(n_cells, min = -1, max = 1) 43 | y <- runif(n_cells, min = -1, max = 1) 44 | r <- sqrt(x^2 + y^2) 45 | points <- data.frame(x, y, r) 46 | points <- points[order(r), ] 47 | r0 <- 1 / sqrt(n_rings) 48 | radii_thres <- c(0, sqrt(seq(n_rings)) * r0, Inf) 49 | points$group <- 50 | factor(cut(points$r, radii_thres), labels = seq(n_rings + 1)) 51 | points <- points[points$group != n_rings + 1, ] 52 | points$group <- droplevels(points$group) 53 | n_cells <- nrow(points) 54 | 55 | # Generate expression 56 | counts <- matrix(rpois(n_genes * n_cells, lambda = rate), 57 | nrow = n_genes, 58 | ncol = n_cells 59 | ) 60 | n_pring <- floor(n_genes / n_rings) 61 | gene_idx <- 62 | split(seq(n_pring * n_rings), rep(seq(n_rings), each = n_pring)) 63 | for (i in seq(n_rings)) { 64 | curr_gid <- gene_idx[[i]] 65 | curr_cid <- which(points$group == i) 66 | counts[curr_gid, curr_cid] <- 67 | counts[curr_gid, curr_cid] + 68 | rpois(length(curr_gid) * length(curr_cid), lambda = rate / 2) 69 | } 70 | locs <- as.matrix(points[, c("x", "y")]) 71 | se <- SpatialExperiment( 72 | assays = list(counts = counts), 73 | spatialCoords = locs, 74 | colData = data.frame(cluster = points$group, in_tissue = TRUE) 75 | ) 76 | rownames(se) <- paste0("gene_", seq(nrow(se))) 77 | colnames(se) <- paste0("cell_", seq(ncol(se))) 78 | se 79 | } 80 | 81 | # Set seed with verbosity. 82 | verbose.seed <- function(seed) { 83 | if (!is.null(seed)) { 84 | set.seed(seed) 85 | message("Using seed=", seed) 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | #' @importFrom utils packageVersion 2 | .onAttach <- function(libname, pkgname) { 3 | if (!interactive()) { 4 | return() 5 | } 6 | 7 | packageStartupMessage( 8 | sprintf("Banksy version %s", packageVersion(pkg = "Banksy")) 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: github_document 3 | --- 4 | 5 | 6 | 7 | ```{r, include = FALSE} 8 | knitr::opts_chunk$set( 9 | collapse = TRUE, 10 | comment = "#>", 11 | fig.path = "man/figures/README-", 12 | out.width = "100%", 13 | dpi = 70 14 | ) 15 | ``` 16 | 17 | ## Overview 18 | 19 | ```{r, eval=T, include=F} 20 | start.time <- Sys.time() 21 | ``` 22 | 23 | BANKSY is a method for clustering spatial omics data by augmenting the 24 | features of each cell with both an average of the features of its spatial 25 | neighbors along with neighborhood feature gradients. By incorporating 26 | neighborhood information for clustering, BANKSY is able to 27 | 28 | - improve cell-type assignment in noisy data 29 | - distinguish subtly different cell-types stratified by microenvironment 30 | - identify spatial domains sharing the same microenvironment 31 | 32 | BANKSY is applicable to a wide array of spatial technologies (e.g. 10x Visium, 33 | Slide-seq, MERFISH, CosMX, CODEX) and scales well to large datasets. For more 34 | details, check out: 35 | 36 | - the [paper](https://www.nature.com/articles/s41588-024-01664-3), 37 | - the [peer review file](https://static-content.springer.com/esm/art%3A10.1038%2Fs41588-024-01664-3/MediaObjects/41588_2024_1664_MOESM3_ESM.pdf), 38 | - a [tweetorial](https://x.com/shyam_lab/status/1762648072360792479?s=20) on BANKSY, 39 | - a set of [vignettes](https://prabhakarlab.github.io/Banksy) showing basic 40 | usage, 41 | - usage compatibility with Seurat ([here](https://github.com/satijalab/seurat-wrappers/blob/master/docs/banksy.md) and [here](https://satijalab.org/seurat/articles/visiumhd_analysis_vignette#identifying-spatially-defined-tissue-domains)), 42 | - a [Python version](https://github.com/prabhakarlab/Banksy_py) of this package, 43 | - a [Zenodo archive](https://zenodo.org/records/10258795) containing scripts to 44 | reproduce the analyses in the paper, and the corresponding 45 | [GitHub Pages](https://github.com/jleechung/banksy-zenodo) 46 | (and [here](https://github.com/prabhakarlab/Banksy_py/tree/Banksy_manuscript) for analyses done in Python). 47 | 48 | ## Installation 49 | 50 | The *Banksy* package can be installed via Bioconductor. This currently requires 51 | R `>= 4.4.0`. 52 | 53 | ```{r, eval=F} 54 | BiocManager::install('Banksy') 55 | ``` 56 | 57 | To install directly from GitHub instead, use 58 | 59 | ```{r, eval=F} 60 | remotes::install_github("prabhakarlab/Banksy") 61 | ``` 62 | 63 | To use the legacy version of *Banksy* utilising the `BanksyObject` class, use 64 | 65 | ```{r, eval=F} 66 | remotes::install_github("prabhakarlab/Banksy@legacy") 67 | ``` 68 | 69 | *Banksy* is also interoperable with [*Seurat*](https://satijalab.org/seurat/) 70 | via [*SeuratWrappers*](https://github.com/satijalab/seurat-wrappers). 71 | Documentation on how to run BANKSY on Seurat objects can be found [here](https://github.com/satijalab/seurat-wrappers/blob/master/docs/banksy.md). 72 | For installation of *SeuratWrappers* with BANKSY version `>= 0.1.6`, run 73 | 74 | ```{r, eval=F} 75 | remotes::install_github('satijalab/seurat-wrappers') 76 | ``` 77 | 78 | ## Quick start 79 | 80 | Load *BANKSY*. We'll also load *SpatialExperiment* and *SummarizedExperiment* 81 | for containing and manipulating the data, *scuttle* for normalization 82 | and quality control, and *scater*, *ggplot2* and *cowplot* for visualisation. 83 | 84 | ```{r, eval=T, warning=F, message=F} 85 | library(Banksy) 86 | 87 | library(SummarizedExperiment) 88 | library(SpatialExperiment) 89 | library(scuttle) 90 | 91 | library(scater) 92 | library(cowplot) 93 | library(ggplot2) 94 | ``` 95 | 96 | Here, we'll run *BANKSY* on mouse hippocampus data. 97 | 98 | ```{r, eval=T} 99 | data(hippocampus) 100 | gcm <- hippocampus$expression 101 | locs <- as.matrix(hippocampus$locations) 102 | ``` 103 | 104 | Initialize a SpatialExperiment object and perform basic quality control and 105 | normalization. 106 | 107 | ```{r, eval=T, message=F} 108 | se <- SpatialExperiment(assay = list(counts = gcm), spatialCoords = locs) 109 | 110 | # QC based on total counts 111 | qcstats <- perCellQCMetrics(se) 112 | thres <- quantile(qcstats$total, c(0.05, 0.98)) 113 | keep <- (qcstats$total > thres[1]) & (qcstats$total < thres[2]) 114 | se <- se[, keep] 115 | 116 | # Normalization to mean library size 117 | se <- computeLibraryFactors(se) 118 | aname <- "normcounts" 119 | assay(se, aname) <- normalizeCounts(se, log = FALSE) 120 | ``` 121 | 122 | Compute the neighborhood matrices for *BANKSY*. Setting `compute_agf=TRUE` 123 | computes both the weighted neighborhood mean ($\mathcal{M}$) and the azimuthal 124 | Gabor filter ($\mathcal{G}$). The number of spatial neighbors used to compute 125 | $\mathcal{M}$ and $\mathcal{G}$ are `k_geom[1]=15` and `k_geom[2]=30` 126 | respectively. We run *BANKSY* at `lambda=0` corresponding to non-spatial 127 | clustering, and `lambda=0.2` corresponding to *BANKSY* for cell-typing. 128 | 129 | > **An important note about choosing the `lambda` parameter for the older [Visium v1 / v2 55um datasets](https://doi.org/10.1038/s41593-020-00787-0) or the original [ST 100um technology](https://doi.org/10.1038/s41596-018-0045-2):** 130 | > 131 | > For most modern high resolution technologies like Xenium, Visium HD, StereoSeq, MERFISH, STARmap PLUS, SeqFISH+, SlideSeq v2, and CosMx (and others), we recommend the usual defults for `lambda`: For cell typing, use `lambda = 0.2` (as shown below, or in [this vignette](https://prabhakarlab.github.io/Banksy/articles/parameter-selection.html)) and for [domain segmentation](https://prabhakarlab.github.io/Banksy/articles/domain-segment.html), use `lambda = 0.8`. These technologies are either imaging based, having true single-cell resolution (e.g., MERFISH), or are sequencing based, having barcoded spots on the scale of single-cells (e.g., [Visium HD](https://www.10xgenomics.com/products/visium-hd-spatial-gene-expression)). We find that the usual defaults work well at this measurement resolution. 132 | > 133 | > However, for the older **Visium v1/v2** or **ST** technologies, with their much lower resolution spots (55um and 100um diameter, respectively), we find that `lambda = 0.2` seems to work best for domain segmentation. This could be because each spot already measures the average transcriptome of several cells in a neighbourhood. It seems that `lambda = 0.2` shares enough information between these neighbourhoods to lead to good domain segmentation performance. For example, in the [human DLPFC vignette](https://prabhakarlab.github.io/Banksy/articles/multi-sample.html), we use `lambda = 0.2` on a Visium v1/v2 dataset. Also note that in these lower resolution technologies, each spot can have multiple cells of different types, and as such _cell-typing_ is not defined for them. 134 | 135 | 136 | ```{r, eval=T} 137 | lambda <- c(0, 0.2) 138 | k_geom <- c(15, 30) 139 | 140 | se <- Banksy::computeBanksy(se, assay_name = aname, compute_agf = TRUE, k_geom = k_geom) 141 | ``` 142 | 143 | Next, run PCA on the BANKSY matrix and perform clustering. Setting 144 | `use_agf=TRUE` uses both $\mathcal{M}$ and $\mathcal{G}$ to construct the 145 | BANKSY matrix. 146 | 147 | ```{r, eval=T} 148 | set.seed(1000) 149 | se <- Banksy::runBanksyPCA(se, use_agf = TRUE, lambda = lambda) 150 | se <- Banksy::runBanksyUMAP(se, use_agf = TRUE, lambda = lambda) 151 | se <- Banksy::clusterBanksy(se, use_agf = TRUE, lambda = lambda, resolution = 1.2) 152 | ``` 153 | 154 | Different clustering runs can be relabeled to minimise their differences with 155 | `connectClusters`: 156 | 157 | ```{r, eval=T} 158 | se <- Banksy::connectClusters(se) 159 | ``` 160 | 161 | Visualise the clustering output for non-spatial clustering (`lambda=0`) and 162 | BANKSY clustering (`lambda=0.2`). 163 | 164 | ```{r, eval=T, fig.height=5, fig.width=14} 165 | cnames <- colnames(colData(se)) 166 | cnames <- cnames[grep("^clust", cnames)] 167 | colData(se) <- cbind(colData(se), spatialCoords(se)) 168 | 169 | plot_nsp <- plotColData(se, 170 | x = "sdimx", y = "sdimy", 171 | point_size = 0.6, colour_by = cnames[1] 172 | ) 173 | plot_bank <- plotColData(se, 174 | x = "sdimx", y = "sdimy", 175 | point_size = 0.6, colour_by = cnames[2] 176 | ) 177 | 178 | 179 | plot_grid(plot_nsp + coord_equal(), plot_bank + coord_equal(), ncol = 2) 180 | ``` 181 | 182 | For clarity, we can visualise each of the clusters separately: 183 | 184 | ```{r, eval=T, fig.height=8, fig.width=18} 185 | plot_grid( 186 | plot_nsp + facet_wrap(~colour_by), 187 | plot_bank + facet_wrap(~colour_by), 188 | ncol = 2 189 | ) 190 | ``` 191 | 192 | Visualize UMAPs of the non-spatial and BANKSY embedding: 193 | 194 | ```{r, eval=T, fig.height=5, fig.width=14} 195 | rdnames <- reducedDimNames(se) 196 | 197 | umap_nsp <- plotReducedDim(se, 198 | dimred = grep("UMAP.*lam0$", rdnames, value = TRUE), 199 | colour_by = cnames[1] 200 | ) 201 | umap_bank <- plotReducedDim(se, 202 | dimred = grep("UMAP.*lam0.2$", rdnames, value = TRUE), 203 | colour_by = cnames[2] 204 | ) 205 | plot_grid( 206 | umap_nsp, 207 | umap_bank, 208 | ncol = 2 209 | ) 210 | ``` 211 | 212 |
213 | Runtime for analysis 214 | 215 | ```{r, eval=T, echo=FALSE} 216 | Sys.time() - start.time 217 | ``` 218 | 219 |
220 | 221 |
222 | Session information 223 | 224 | ```{r, sess} 225 | sessionInfo() 226 | ``` 227 | 228 |
229 | 230 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://prabhakarlab.github.io/Banksy 2 | 3 | development: 4 | mode: auto 5 | 6 | template: 7 | bootswatch: simplex 8 | 9 | reference: 10 | - title: Neighborhood matrix computation 11 | contents: 12 | - computeBanksy 13 | - getBanksyMatrix 14 | - title: Dimensionality reduction 15 | contents: 16 | - runBanksyPCA 17 | - runBanksyUMAP 18 | - title: Clustering 19 | contents: 20 | - clusterBanksy 21 | - connectClusters 22 | - compareClusters 23 | - smoothLabels 24 | - clusterNames 25 | - title: Datasets 26 | contents: 27 | - hippocampus 28 | - rings 29 | - title: Misc. 30 | contents: 31 | - simulateDataset 32 | 33 | news: 34 | cran_dates: false 35 | 36 | navbar: 37 | title: ~ 38 | type: default 39 | left: 40 | - text: Functions and data 41 | href: reference/index.html 42 | - text: Vignettes 43 | menu: 44 | - text: BANKSY parameter selection (VeraFISH Mouse Hippocampus) 45 | href: articles/parameter-selection.html 46 | - text: Domain segmentation (STARmap PLUS Mouse brain) 47 | href: articles/domain-segment.html 48 | - text: Spatial data integration with Harmony (10x Visium Human DLPFC) 49 | href: articles/batch-correction.html 50 | - text: Analysing multiple datasets (10x Visium Human DLPFC) 51 | href: articles/multi-sample.html 52 | - text: News 53 | href: news/index.html 54 | -------------------------------------------------------------------------------- /data/hippocampus.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/data/hippocampus.rda -------------------------------------------------------------------------------- /data/rings.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/data/rings.rda -------------------------------------------------------------------------------- /docs/404.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Page not found (404) • Banksy 9 | 10 | 11 | 12 | 13 | 14 | 15 | 19 | 20 | 21 | 22 | 23 |
24 |
82 | 83 | 84 | 85 | 86 |
87 |
88 | 91 | 92 | Content not found. Please use links in the navbar. 93 | 94 |
95 | 96 | 100 | 101 |
102 | 103 | 104 | 105 |
109 | 110 |
111 |

112 |

Site built with pkgdown 2.0.7.

113 |
114 | 115 |
116 |
117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /docs/LICENSE-text.html: -------------------------------------------------------------------------------- 1 | 2 | License • Banksy 6 | 7 | 8 |
9 |
59 | 60 | 61 | 62 |
63 |
64 | 67 | 68 |
 69 | USER LICENSE for the software suite BANKSY
 70 | 
 71 | TLDR (see below for details). 
 72 | Academic usage: MIT License
 73 | Commercial Usage: Restrictions applicable, see below. 
 74 | 
 75 | Authorship and Copyright (c) 
 76 | 2022; Vipul Singhal, Joseph Lee
 77 | 
 78 | References of associated scientific publications
 79 | 1) Singhal, V., Chou, N., Lee, J. et al. BANKSY unifies cell typing and tissue domain segmentation for scalable spatial omics data analysis. Nat Genet 56, 431–441 (2024). https://doi.org/10.1038/s41588-024-01664-3
 80 | 
 81 | ***
 82 | 
 83 | Vipul Singhal
 84 | vipul_singhal@gis.a-star.edu.sg
 85 | Genome Institute of Singapore, 60 Biopolis Street, Singapore 138672
 86 | 
 87 | Joseph Lee
 88 | joseph.lee@u.nus.edu
 89 | Genome Institute of Singapore, 60 Biopolis Street, Singapore 138672
 90 | 
 91 | ***
 92 | 
 93 | License conditions
 94 | 
 95 | 1. Definitions
 96 | 
 97 | “Author” refers to the person(s) that hold the authors’ rights or to an organization that has been entitled by them or their employer during the work on the software suite to protect the respective rights and to issue user licenses. 
 98 | 
 99 | “Software” includes all program or database files as well as associated documentation files together with this license document. 
100 | 
101 | This license refers to the software suite in the title of this document with all its author’s versions. This includes the newest one and any preceding version - be it in “source code form” (the preferred form of the work for making modifications to it) or “object form” (any compiled/executable version of it). This license covers both the whole software as well as any part of it. It is applicable to the standalone versions of this software as well as its incorporation as integral part into other software packages. 
102 | 
103 | “User” is the licensee of this software. 
104 | 
105 | 2. Copyright notice
106 | 
107 | All rights are reserved, whether the whole or part of the software is concerned. The software may not be used or distributed without specific, prior written permission of the author beyond the exceptions described in this license. 
108 | 
109 | This especially concerns respecting the authors’ rights. The user will always refer to the authors, their publications and this software package when communicating about this software, any of its modifications or about results obtained with this software. 
110 | 
111 | The copyright messages (if any) will not be modified or suppressed. The software package will always remain associated with this license agreement.
112 | 
113 | 3. Academic (non-commercial) usage: MIT License
114 | 
115 | Copyright (c) <2022> <Vipul Singhal, Joseph Lee>
116 | 
117 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
118 | 
119 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
120 | 
121 | 4. Commercial usage
122 | 
123 | The usage of this software in commercial activities is not allowed without a prior written commercial licence agreement issued by the author. 
124 | 
125 | Any software package that contains this software or parts of it can only be commercialized with a license agreement issued by the author. 
126 | 
127 | 5. Warranty and liability
128 | 
129 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 
130 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING OUT OF OR IN CONNECTION WITH THE USE, PERFORMANCE OF THIS SOFTWARE OR ANY OTHER DEALINGS WITH IT, WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY. 
131 | 
132 | 133 |
134 | 135 | 138 | 139 |
140 | 141 | 142 | 143 |
146 | 147 |
148 |

Site built with pkgdown 2.0.7.

149 |
150 | 151 |
152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /docs/articles/figures/batch-correction-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/articles/figures/batch-correction-spatial-1.png -------------------------------------------------------------------------------- /docs/articles/figures/batch-correction-umap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/articles/figures/batch-correction-umap-1.png -------------------------------------------------------------------------------- /docs/articles/figures/domain-segment-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/articles/figures/domain-segment-spatial-1.png -------------------------------------------------------------------------------- /docs/articles/figures/multi-sample-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/articles/figures/multi-sample-spatial-1.png -------------------------------------------------------------------------------- /docs/articles/figures/multi-sample-umap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/articles/figures/multi-sample-umap-1.png -------------------------------------------------------------------------------- /docs/articles/figures/parameter-selection-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/articles/figures/parameter-selection-spatial-1.png -------------------------------------------------------------------------------- /docs/articles/index.html: -------------------------------------------------------------------------------- 1 | 2 | Articles • Banksy 6 | 7 | 8 |
9 |
59 | 60 | 61 | 62 |
83 | 84 | 85 |
88 | 89 |
90 |

Site built with pkgdown 2.0.7.

91 |
92 | 93 |
94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /docs/authors.html: -------------------------------------------------------------------------------- 1 | 2 | Authors and Citation • Banksy 6 | 7 | 8 |
9 |
59 | 60 | 61 | 62 |
63 |
64 |
65 | 68 | 69 | 70 |
  • 71 |

    Vipul Singhal. Author. 72 |

    73 |
  • 74 |
  • 75 |

    Joseph Lee. Author, maintainer. 76 |

    77 |
  • 78 |
79 |
80 |
81 |

Citation

82 | Source: inst/CITATION 83 |
84 |
85 | 86 | 87 |

Singhal, V., Chou, N., et al. BANKSY: A Spatial Omics Algorithm that Unifies Cell Typing and Tissue Domain Segmentation Preprint at bioRxiv https://doi.org/10.1101/2022.04.14.488259 (2022)

88 |
@Article{,
 89 |   title = {BANKSY: A Spatial Omics Algorithm that Unifies Cell Typing and Tissue Domain Segmentation},
 90 |   author = {Vipul Singhal and Nigel Chou and Joseph Lee and Jinyue Liu and Wan Kee Chock and Li Lin and Yun-Ching Chang and Erica Teo and Hwee Kuan Lee and Kok Hao Chen and Shyam Prabhakar},
 91 |   journal = {bioRxiv},
 92 |   year = {2022},
 93 |   url = {https://www.biorxiv.org/content/10.1101/2022.04.14.488259},
 94 | }
95 | 96 |
97 | 98 |
99 | 100 | 101 | 102 |
105 | 106 |
107 |

Site built with pkgdown 2.0.7.

108 |
109 | 110 |
111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | 6 | /* modified from https://github.com/twbs/bootstrap/blob/94b4076dd2efba9af71f0b18d4ee4b163aa9e0dd/docs/assets/css/src/docs.css#L548-L601 */ 7 | 8 | /* All levels of nav */ 9 | nav[data-toggle='toc'] .nav > li > a { 10 | display: block; 11 | padding: 4px 20px; 12 | font-size: 13px; 13 | font-weight: 500; 14 | color: #767676; 15 | } 16 | nav[data-toggle='toc'] .nav > li > a:hover, 17 | nav[data-toggle='toc'] .nav > li > a:focus { 18 | padding-left: 19px; 19 | color: #563d7c; 20 | text-decoration: none; 21 | background-color: transparent; 22 | border-left: 1px solid #563d7c; 23 | } 24 | nav[data-toggle='toc'] .nav > .active > a, 25 | nav[data-toggle='toc'] .nav > .active:hover > a, 26 | nav[data-toggle='toc'] .nav > .active:focus > a { 27 | padding-left: 18px; 28 | font-weight: bold; 29 | color: #563d7c; 30 | background-color: transparent; 31 | border-left: 2px solid #563d7c; 32 | } 33 | 34 | /* Nav: second level (shown on .active) */ 35 | nav[data-toggle='toc'] .nav .nav { 36 | display: none; /* Hide by default, but at >768px, show it */ 37 | padding-bottom: 10px; 38 | } 39 | nav[data-toggle='toc'] .nav .nav > li > a { 40 | padding-top: 1px; 41 | padding-bottom: 1px; 42 | padding-left: 30px; 43 | font-size: 12px; 44 | font-weight: normal; 45 | } 46 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 47 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 48 | padding-left: 29px; 49 | } 50 | nav[data-toggle='toc'] .nav .nav > .active > a, 51 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 52 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 53 | padding-left: 28px; 54 | font-weight: 500; 55 | } 56 | 57 | /* from https://github.com/twbs/bootstrap/blob/e38f066d8c203c3e032da0ff23cd2d6098ee2dd6/docs/assets/css/src/docs.css#L631-L634 */ 58 | nav[data-toggle='toc'] .nav > .active > ul { 59 | display: block; 60 | } 61 | -------------------------------------------------------------------------------- /docs/bootstrap-toc.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Table of Contents v0.4.1 (http://afeld.github.io/bootstrap-toc/) 3 | * Copyright 2015 Aidan Feldman 4 | * Licensed under MIT (https://github.com/afeld/bootstrap-toc/blob/gh-pages/LICENSE.md) */ 5 | (function() { 6 | 'use strict'; 7 | 8 | window.Toc = { 9 | helpers: { 10 | // return all matching elements in the set, or their descendants 11 | findOrFilter: function($el, selector) { 12 | // http://danielnouri.org/notes/2011/03/14/a-jquery-find-that-also-finds-the-root-element/ 13 | // http://stackoverflow.com/a/12731439/358804 14 | var $descendants = $el.find(selector); 15 | return $el.filter(selector).add($descendants).filter(':not([data-toc-skip])'); 16 | }, 17 | 18 | generateUniqueIdBase: function(el) { 19 | var text = $(el).text(); 20 | var anchor = text.trim().toLowerCase().replace(/[^A-Za-z0-9]+/g, '-'); 21 | return anchor || el.tagName.toLowerCase(); 22 | }, 23 | 24 | generateUniqueId: function(el) { 25 | var anchorBase = this.generateUniqueIdBase(el); 26 | for (var i = 0; ; i++) { 27 | var anchor = anchorBase; 28 | if (i > 0) { 29 | // add suffix 30 | anchor += '-' + i; 31 | } 32 | // check if ID already exists 33 | if (!document.getElementById(anchor)) { 34 | return anchor; 35 | } 36 | } 37 | }, 38 | 39 | generateAnchor: function(el) { 40 | if (el.id) { 41 | return el.id; 42 | } else { 43 | var anchor = this.generateUniqueId(el); 44 | el.id = anchor; 45 | return anchor; 46 | } 47 | }, 48 | 49 | createNavList: function() { 50 | return $(''); 51 | }, 52 | 53 | createChildNavList: function($parent) { 54 | var $childList = this.createNavList(); 55 | $parent.append($childList); 56 | return $childList; 57 | }, 58 | 59 | generateNavEl: function(anchor, text) { 60 | var $a = $(''); 61 | $a.attr('href', '#' + anchor); 62 | $a.text(text); 63 | var $li = $('
  • '); 64 | $li.append($a); 65 | return $li; 66 | }, 67 | 68 | generateNavItem: function(headingEl) { 69 | var anchor = this.generateAnchor(headingEl); 70 | var $heading = $(headingEl); 71 | var text = $heading.data('toc-text') || $heading.text(); 72 | return this.generateNavEl(anchor, text); 73 | }, 74 | 75 | // Find the first heading level (`

    `, then `

    `, etc.) that has more than one element. Defaults to 1 (for `

    `). 76 | getTopLevel: function($scope) { 77 | for (var i = 1; i <= 6; i++) { 78 | var $headings = this.findOrFilter($scope, 'h' + i); 79 | if ($headings.length > 1) { 80 | return i; 81 | } 82 | } 83 | 84 | return 1; 85 | }, 86 | 87 | // returns the elements for the top level, and the next below it 88 | getHeadings: function($scope, topLevel) { 89 | var topSelector = 'h' + topLevel; 90 | 91 | var secondaryLevel = topLevel + 1; 92 | var secondarySelector = 'h' + secondaryLevel; 93 | 94 | return this.findOrFilter($scope, topSelector + ',' + secondarySelector); 95 | }, 96 | 97 | getNavLevel: function(el) { 98 | return parseInt(el.tagName.charAt(1), 10); 99 | }, 100 | 101 | populateNav: function($topContext, topLevel, $headings) { 102 | var $context = $topContext; 103 | var $prevNav; 104 | 105 | var helpers = this; 106 | $headings.each(function(i, el) { 107 | var $newNav = helpers.generateNavItem(el); 108 | var navLevel = helpers.getNavLevel(el); 109 | 110 | // determine the proper $context 111 | if (navLevel === topLevel) { 112 | // use top level 113 | $context = $topContext; 114 | } else if ($prevNav && $context === $topContext) { 115 | // create a new level of the tree and switch to it 116 | $context = helpers.createChildNavList($prevNav); 117 | } // else use the current $context 118 | 119 | $context.append($newNav); 120 | 121 | $prevNav = $newNav; 122 | }); 123 | }, 124 | 125 | parseOps: function(arg) { 126 | var opts; 127 | if (arg.jquery) { 128 | opts = { 129 | $nav: arg 130 | }; 131 | } else { 132 | opts = arg; 133 | } 134 | opts.$scope = opts.$scope || $(document.body); 135 | return opts; 136 | } 137 | }, 138 | 139 | // accepts a jQuery object, or an options object 140 | init: function(opts) { 141 | opts = this.helpers.parseOps(opts); 142 | 143 | // ensure that the data attribute is in place for styling 144 | opts.$nav.attr('data-toggle', 'toc'); 145 | 146 | var $topContext = this.helpers.createChildNavList(opts.$nav); 147 | var topLevel = this.helpers.getTopLevel(opts.$scope); 148 | var $headings = this.helpers.getHeadings(opts.$scope, topLevel); 149 | this.helpers.populateNav($topContext, topLevel, $headings); 150 | } 151 | }; 152 | 153 | $(function() { 154 | $('nav[data-toggle="toc"]').each(function(i, el) { 155 | var $nav = $(el); 156 | Toc.init($nav); 157 | }); 158 | }); 159 | })(); 160 | -------------------------------------------------------------------------------- /docs/docsearch.js: -------------------------------------------------------------------------------- 1 | $(function() { 2 | 3 | // register a handler to move the focus to the search bar 4 | // upon pressing shift + "/" (i.e. "?") 5 | $(document).on('keydown', function(e) { 6 | if (e.shiftKey && e.keyCode == 191) { 7 | e.preventDefault(); 8 | $("#search-input").focus(); 9 | } 10 | }); 11 | 12 | $(document).ready(function() { 13 | // do keyword highlighting 14 | /* modified from https://jsfiddle.net/julmot/bL6bb5oo/ */ 15 | var mark = function() { 16 | 17 | var referrer = document.URL ; 18 | var paramKey = "q" ; 19 | 20 | if (referrer.indexOf("?") !== -1) { 21 | var qs = referrer.substr(referrer.indexOf('?') + 1); 22 | var qs_noanchor = qs.split('#')[0]; 23 | var qsa = qs_noanchor.split('&'); 24 | var keyword = ""; 25 | 26 | for (var i = 0; i < qsa.length; i++) { 27 | var currentParam = qsa[i].split('='); 28 | 29 | if (currentParam.length !== 2) { 30 | continue; 31 | } 32 | 33 | if (currentParam[0] == paramKey) { 34 | keyword = decodeURIComponent(currentParam[1].replace(/\+/g, "%20")); 35 | } 36 | } 37 | 38 | if (keyword !== "") { 39 | $(".contents").unmark({ 40 | done: function() { 41 | $(".contents").mark(keyword); 42 | } 43 | }); 44 | } 45 | } 46 | }; 47 | 48 | mark(); 49 | }); 50 | }); 51 | 52 | /* Search term highlighting ------------------------------*/ 53 | 54 | function matchedWords(hit) { 55 | var words = []; 56 | 57 | var hierarchy = hit._highlightResult.hierarchy; 58 | // loop to fetch from lvl0, lvl1, etc. 59 | for (var idx in hierarchy) { 60 | words = words.concat(hierarchy[idx].matchedWords); 61 | } 62 | 63 | var content = hit._highlightResult.content; 64 | if (content) { 65 | words = words.concat(content.matchedWords); 66 | } 67 | 68 | // return unique words 69 | var words_uniq = [...new Set(words)]; 70 | return words_uniq; 71 | } 72 | 73 | function updateHitURL(hit) { 74 | 75 | var words = matchedWords(hit); 76 | var url = ""; 77 | 78 | if (hit.anchor) { 79 | url = hit.url_without_anchor + '?q=' + escape(words.join(" ")) + '#' + hit.anchor; 80 | } else { 81 | url = hit.url + '?q=' + escape(words.join(" ")); 82 | } 83 | 84 | return url; 85 | } 86 | -------------------------------------------------------------------------------- /docs/link.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | 12 | 13 | -------------------------------------------------------------------------------- /docs/news/index.html: -------------------------------------------------------------------------------- 1 | 2 | Changelog • Banksy 6 | 7 | 8 |
    9 |
    59 | 60 | 61 | 62 |
    63 |
    64 | 68 | 69 |
    70 | 71 |
    • Add feature scaling options for PCA and UMAP
    • 72 |
    73 |
    74 | 75 |
    • SCE/SPE-compatible
    • 76 |
    77 |
    78 | 79 |
    • Fix compatibility with SeuratWrappers
    • 80 |
    81 |
    82 | 83 |
    • Implemented SmoothLabels for k-nearest neighbors cluster label smoothing
    • 84 |
    • Parallel clustering for Leiden graph-based clustering
    • 85 |
    • Version depedency on leidenAlg (>= 1.1.0) for compatibility with igraph (>= 1.5.0)
    • 86 |
    • Seed setting for clustering
    • 87 |
    • Neighborhood sampling for computing neighborhood feature matrices. See arguments sample_size, sample_renorm and seed in function ComputeBanksy
    • 88 |
    89 |
    90 | 91 |
    • Implemented Azimuthal Gabor filters in ComputeBanksy, with the number of harmonics determined by the M argument. To obtain similar results as version 0.1.3, use M=0 92 |
    • 93 |
    • RunPCA and RunUMAP renamed to RunBanksyPCA and RunBanksyUMAP respectively to avoid namespace collisions with other packages
    • 94 |
    • Changed some function argument names (e.g. spatialMode to spatial_mode)
    • 95 |
    96 |
    97 | 98 |
    • Interoperability with SingleCellExperiment with asBanksyObject
    • 99 |
    • Passing Bioc and R CMD checks
    • 100 |
    101 |
    102 | 103 |
    • BanksyObject: dimensionality reduction slot name changed to reduction
    • 104 |
    • RunPCA and RunUMAP
    • 105 |
    • Plotting is generalised (plotReduction instead of plotUMAP / plotPCA)
    • 106 |
    • ConnectClusters improved and returns BanksyObject
    • 107 |
    • ARI computation and plotting
    • 108 |
    109 |
    110 | 111 |
    • Legacy version
    • 112 |
    113 |
    114 | 115 | 118 | 119 |
    120 | 121 | 122 |
    125 | 126 |
    127 |

    Site built with pkgdown 2.0.7.

    128 |
    129 | 130 |
    131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /docs/pkgdown.css: -------------------------------------------------------------------------------- 1 | /* Sticky footer */ 2 | 3 | /** 4 | * Basic idea: https://philipwalton.github.io/solved-by-flexbox/demos/sticky-footer/ 5 | * Details: https://github.com/philipwalton/solved-by-flexbox/blob/master/assets/css/components/site.css 6 | * 7 | * .Site -> body > .container 8 | * .Site-content -> body > .container .row 9 | * .footer -> footer 10 | * 11 | * Key idea seems to be to ensure that .container and __all its parents__ 12 | * have height set to 100% 13 | * 14 | */ 15 | 16 | html, body { 17 | height: 100%; 18 | } 19 | 20 | body { 21 | position: relative; 22 | } 23 | 24 | body > .container { 25 | display: flex; 26 | height: 100%; 27 | flex-direction: column; 28 | } 29 | 30 | body > .container .row { 31 | flex: 1 0 auto; 32 | } 33 | 34 | footer { 35 | margin-top: 45px; 36 | padding: 35px 0 36px; 37 | border-top: 1px solid #e5e5e5; 38 | color: #666; 39 | display: flex; 40 | flex-shrink: 0; 41 | } 42 | footer p { 43 | margin-bottom: 0; 44 | } 45 | footer div { 46 | flex: 1; 47 | } 48 | footer .pkgdown { 49 | text-align: right; 50 | } 51 | footer p { 52 | margin-bottom: 0; 53 | } 54 | 55 | img.icon { 56 | float: right; 57 | } 58 | 59 | /* Ensure in-page images don't run outside their container */ 60 | .contents img { 61 | max-width: 100%; 62 | height: auto; 63 | } 64 | 65 | /* Fix bug in bootstrap (only seen in firefox) */ 66 | summary { 67 | display: list-item; 68 | } 69 | 70 | /* Typographic tweaking ---------------------------------*/ 71 | 72 | .contents .page-header { 73 | margin-top: calc(-60px + 1em); 74 | } 75 | 76 | dd { 77 | margin-left: 3em; 78 | } 79 | 80 | /* Section anchors ---------------------------------*/ 81 | 82 | a.anchor { 83 | display: none; 84 | margin-left: 5px; 85 | width: 20px; 86 | height: 20px; 87 | 88 | background-image: url(./link.svg); 89 | background-repeat: no-repeat; 90 | background-size: 20px 20px; 91 | background-position: center center; 92 | } 93 | 94 | h1:hover .anchor, 95 | h2:hover .anchor, 96 | h3:hover .anchor, 97 | h4:hover .anchor, 98 | h5:hover .anchor, 99 | h6:hover .anchor { 100 | display: inline-block; 101 | } 102 | 103 | /* Fixes for fixed navbar --------------------------*/ 104 | 105 | .contents h1, .contents h2, .contents h3, .contents h4 { 106 | padding-top: 60px; 107 | margin-top: -40px; 108 | } 109 | 110 | /* Navbar submenu --------------------------*/ 111 | 112 | .dropdown-submenu { 113 | position: relative; 114 | } 115 | 116 | .dropdown-submenu>.dropdown-menu { 117 | top: 0; 118 | left: 100%; 119 | margin-top: -6px; 120 | margin-left: -1px; 121 | border-radius: 0 6px 6px 6px; 122 | } 123 | 124 | .dropdown-submenu:hover>.dropdown-menu { 125 | display: block; 126 | } 127 | 128 | .dropdown-submenu>a:after { 129 | display: block; 130 | content: " "; 131 | float: right; 132 | width: 0; 133 | height: 0; 134 | border-color: transparent; 135 | border-style: solid; 136 | border-width: 5px 0 5px 5px; 137 | border-left-color: #cccccc; 138 | margin-top: 5px; 139 | margin-right: -10px; 140 | } 141 | 142 | .dropdown-submenu:hover>a:after { 143 | border-left-color: #ffffff; 144 | } 145 | 146 | .dropdown-submenu.pull-left { 147 | float: none; 148 | } 149 | 150 | .dropdown-submenu.pull-left>.dropdown-menu { 151 | left: -100%; 152 | margin-left: 10px; 153 | border-radius: 6px 0 6px 6px; 154 | } 155 | 156 | /* Sidebar --------------------------*/ 157 | 158 | #pkgdown-sidebar { 159 | margin-top: 30px; 160 | position: -webkit-sticky; 161 | position: sticky; 162 | top: 70px; 163 | } 164 | 165 | #pkgdown-sidebar h2 { 166 | font-size: 1.5em; 167 | margin-top: 1em; 168 | } 169 | 170 | #pkgdown-sidebar h2:first-child { 171 | margin-top: 0; 172 | } 173 | 174 | #pkgdown-sidebar .list-unstyled li { 175 | margin-bottom: 0.5em; 176 | } 177 | 178 | /* bootstrap-toc tweaks ------------------------------------------------------*/ 179 | 180 | /* All levels of nav */ 181 | 182 | nav[data-toggle='toc'] .nav > li > a { 183 | padding: 4px 20px 4px 6px; 184 | font-size: 1.5rem; 185 | font-weight: 400; 186 | color: inherit; 187 | } 188 | 189 | nav[data-toggle='toc'] .nav > li > a:hover, 190 | nav[data-toggle='toc'] .nav > li > a:focus { 191 | padding-left: 5px; 192 | color: inherit; 193 | border-left: 1px solid #878787; 194 | } 195 | 196 | nav[data-toggle='toc'] .nav > .active > a, 197 | nav[data-toggle='toc'] .nav > .active:hover > a, 198 | nav[data-toggle='toc'] .nav > .active:focus > a { 199 | padding-left: 5px; 200 | font-size: 1.5rem; 201 | font-weight: 400; 202 | color: inherit; 203 | border-left: 2px solid #878787; 204 | } 205 | 206 | /* Nav: second level (shown on .active) */ 207 | 208 | nav[data-toggle='toc'] .nav .nav { 209 | display: none; /* Hide by default, but at >768px, show it */ 210 | padding-bottom: 10px; 211 | } 212 | 213 | nav[data-toggle='toc'] .nav .nav > li > a { 214 | padding-left: 16px; 215 | font-size: 1.35rem; 216 | } 217 | 218 | nav[data-toggle='toc'] .nav .nav > li > a:hover, 219 | nav[data-toggle='toc'] .nav .nav > li > a:focus { 220 | padding-left: 15px; 221 | } 222 | 223 | nav[data-toggle='toc'] .nav .nav > .active > a, 224 | nav[data-toggle='toc'] .nav .nav > .active:hover > a, 225 | nav[data-toggle='toc'] .nav .nav > .active:focus > a { 226 | padding-left: 15px; 227 | font-weight: 500; 228 | font-size: 1.35rem; 229 | } 230 | 231 | /* orcid ------------------------------------------------------------------- */ 232 | 233 | .orcid { 234 | font-size: 16px; 235 | color: #A6CE39; 236 | /* margins are required by official ORCID trademark and display guidelines */ 237 | margin-left:4px; 238 | margin-right:4px; 239 | vertical-align: middle; 240 | } 241 | 242 | /* Reference index & topics ----------------------------------------------- */ 243 | 244 | .ref-index th {font-weight: normal;} 245 | 246 | .ref-index td {vertical-align: top; min-width: 100px} 247 | .ref-index .icon {width: 40px;} 248 | .ref-index .alias {width: 40%;} 249 | .ref-index-icons .alias {width: calc(40% - 40px);} 250 | .ref-index .title {width: 60%;} 251 | 252 | .ref-arguments th {text-align: right; padding-right: 10px;} 253 | .ref-arguments th, .ref-arguments td {vertical-align: top; min-width: 100px} 254 | .ref-arguments .name {width: 20%;} 255 | .ref-arguments .desc {width: 80%;} 256 | 257 | /* Nice scrolling for wide elements --------------------------------------- */ 258 | 259 | table { 260 | display: block; 261 | overflow: auto; 262 | } 263 | 264 | /* Syntax highlighting ---------------------------------------------------- */ 265 | 266 | pre, code, pre code { 267 | background-color: #f8f8f8; 268 | color: #333; 269 | } 270 | pre, pre code { 271 | white-space: pre-wrap; 272 | word-break: break-all; 273 | overflow-wrap: break-word; 274 | } 275 | 276 | pre { 277 | border: 1px solid #eee; 278 | } 279 | 280 | pre .img, pre .r-plt { 281 | margin: 5px 0; 282 | } 283 | 284 | pre .img img, pre .r-plt img { 285 | background-color: #fff; 286 | } 287 | 288 | code a, pre a { 289 | color: #375f84; 290 | } 291 | 292 | a.sourceLine:hover { 293 | text-decoration: none; 294 | } 295 | 296 | .fl {color: #1514b5;} 297 | .fu {color: #000000;} /* function */ 298 | .ch,.st {color: #036a07;} /* string */ 299 | .kw {color: #264D66;} /* keyword */ 300 | .co {color: #888888;} /* comment */ 301 | 302 | .error {font-weight: bolder;} 303 | .warning {font-weight: bolder;} 304 | 305 | /* Clipboard --------------------------*/ 306 | 307 | .hasCopyButton { 308 | position: relative; 309 | } 310 | 311 | .btn-copy-ex { 312 | position: absolute; 313 | right: 0; 314 | top: 0; 315 | visibility: hidden; 316 | } 317 | 318 | .hasCopyButton:hover button.btn-copy-ex { 319 | visibility: visible; 320 | } 321 | 322 | /* headroom.js ------------------------ */ 323 | 324 | .headroom { 325 | will-change: transform; 326 | transition: transform 200ms linear; 327 | } 328 | .headroom--pinned { 329 | transform: translateY(0%); 330 | } 331 | .headroom--unpinned { 332 | transform: translateY(-100%); 333 | } 334 | 335 | /* mark.js ----------------------------*/ 336 | 337 | mark { 338 | background-color: rgba(255, 255, 51, 0.5); 339 | border-bottom: 2px solid rgba(255, 153, 51, 0.3); 340 | padding: 1px; 341 | } 342 | 343 | /* vertical spacing after htmlwidgets */ 344 | .html-widget { 345 | margin-bottom: 10px; 346 | } 347 | 348 | /* fontawesome ------------------------ */ 349 | 350 | .fab { 351 | font-family: "Font Awesome 5 Brands" !important; 352 | } 353 | 354 | /* don't display links in code chunks when printing */ 355 | /* source: https://stackoverflow.com/a/10781533 */ 356 | @media print { 357 | code a:link:after, code a:visited:after { 358 | content: ""; 359 | } 360 | } 361 | 362 | /* Section anchors --------------------------------- 363 | Added in pandoc 2.11: https://github.com/jgm/pandoc-templates/commit/9904bf71 364 | */ 365 | 366 | div.csl-bib-body { } 367 | div.csl-entry { 368 | clear: both; 369 | } 370 | .hanging-indent div.csl-entry { 371 | margin-left:2em; 372 | text-indent:-2em; 373 | } 374 | div.csl-left-margin { 375 | min-width:2em; 376 | float:left; 377 | } 378 | div.csl-right-inline { 379 | margin-left:2em; 380 | padding-left:1em; 381 | } 382 | div.csl-indent { 383 | margin-left: 2em; 384 | } 385 | -------------------------------------------------------------------------------- /docs/pkgdown.js: -------------------------------------------------------------------------------- 1 | /* http://gregfranko.com/blog/jquery-best-practices/ */ 2 | (function($) { 3 | $(function() { 4 | 5 | $('.navbar-fixed-top').headroom(); 6 | 7 | $('body').css('padding-top', $('.navbar').height() + 10); 8 | $(window).resize(function(){ 9 | $('body').css('padding-top', $('.navbar').height() + 10); 10 | }); 11 | 12 | $('[data-toggle="tooltip"]').tooltip(); 13 | 14 | var cur_path = paths(location.pathname); 15 | var links = $("#navbar ul li a"); 16 | var max_length = -1; 17 | var pos = -1; 18 | for (var i = 0; i < links.length; i++) { 19 | if (links[i].getAttribute("href") === "#") 20 | continue; 21 | // Ignore external links 22 | if (links[i].host !== location.host) 23 | continue; 24 | 25 | var nav_path = paths(links[i].pathname); 26 | 27 | var length = prefix_length(nav_path, cur_path); 28 | if (length > max_length) { 29 | max_length = length; 30 | pos = i; 31 | } 32 | } 33 | 34 | // Add class to parent
  • , and enclosing
  • if in dropdown 35 | if (pos >= 0) { 36 | var menu_anchor = $(links[pos]); 37 | menu_anchor.parent().addClass("active"); 38 | menu_anchor.closest("li.dropdown").addClass("active"); 39 | } 40 | }); 41 | 42 | function paths(pathname) { 43 | var pieces = pathname.split("/"); 44 | pieces.shift(); // always starts with / 45 | 46 | var end = pieces[pieces.length - 1]; 47 | if (end === "index.html" || end === "") 48 | pieces.pop(); 49 | return(pieces); 50 | } 51 | 52 | // Returns -1 if not found 53 | function prefix_length(needle, haystack) { 54 | if (needle.length > haystack.length) 55 | return(-1); 56 | 57 | // Special case for length-0 haystack, since for loop won't run 58 | if (haystack.length === 0) { 59 | return(needle.length === 0 ? 0 : -1); 60 | } 61 | 62 | for (var i = 0; i < haystack.length; i++) { 63 | if (needle[i] != haystack[i]) 64 | return(i); 65 | } 66 | 67 | return(haystack.length); 68 | } 69 | 70 | /* Clipboard --------------------------*/ 71 | 72 | function changeTooltipMessage(element, msg) { 73 | var tooltipOriginalTitle=element.getAttribute('data-original-title'); 74 | element.setAttribute('data-original-title', msg); 75 | $(element).tooltip('show'); 76 | element.setAttribute('data-original-title', tooltipOriginalTitle); 77 | } 78 | 79 | if(ClipboardJS.isSupported()) { 80 | $(document).ready(function() { 81 | var copyButton = ""; 82 | 83 | $("div.sourceCode").addClass("hasCopyButton"); 84 | 85 | // Insert copy buttons: 86 | $(copyButton).prependTo(".hasCopyButton"); 87 | 88 | // Initialize tooltips: 89 | $('.btn-copy-ex').tooltip({container: 'body'}); 90 | 91 | // Initialize clipboard: 92 | var clipboardBtnCopies = new ClipboardJS('[data-clipboard-copy]', { 93 | text: function(trigger) { 94 | return trigger.parentNode.textContent.replace(/\n#>[^\n]*/g, ""); 95 | } 96 | }); 97 | 98 | clipboardBtnCopies.on('success', function(e) { 99 | changeTooltipMessage(e.trigger, 'Copied!'); 100 | e.clearSelection(); 101 | }); 102 | 103 | clipboardBtnCopies.on('error', function() { 104 | changeTooltipMessage(e.trigger,'Press Ctrl+C or Command+C to copy'); 105 | }); 106 | }); 107 | } 108 | })(window.jQuery || window.$) 109 | -------------------------------------------------------------------------------- /docs/pkgdown.yml: -------------------------------------------------------------------------------- 1 | pandoc: 3.1.13 2 | pkgdown: 2.0.7 3 | pkgdown_sha: ~ 4 | articles: 5 | batch-correction: batch-correction.html 6 | domain-segment: domain-segment.html 7 | multi-sample: multi-sample.html 8 | parameter-selection: parameter-selection.html 9 | last_built: 2024-05-09T13:15Z 10 | urls: 11 | reference: https://prabhakarlab.github.io/Banksy/reference 12 | article: https://prabhakarlab.github.io/Banksy/articles 13 | 14 | -------------------------------------------------------------------------------- /docs/reference/Banksy-package.html: -------------------------------------------------------------------------------- 1 | 2 | The Banksy package — Banksy-package • Banksy 6 | 7 | 8 |
    9 |
    59 | 60 | 61 | 62 |
    63 |
    64 | 69 | 70 |
    71 |

    Banksy is a library and R package for network analysis.

    72 |
    73 | 74 | 75 |
    76 |

    Description

    77 | 78 | 79 |

    Banksy is an R package that incorporates spatial information to cluster 80 | cells in a feature space (e.g. gene expression). To incorporate spatial 81 | information, BANKSY computes the mean neighborhood expression and azimuthal 82 | Gabor filters that capture gene expression gradients. These features are 83 | combined with the cell's own expression to embed cells in a 84 | neighbor-augmented product space which can then be clustered, allowing for 85 | accurate and spatially-aware cell typing and tissue domain segmentation.

    86 |
    87 |
    88 |

    Details

    89 | 90 | 91 |

    For a quick start to the package, please refer to the GitHub page at 92 | https://github.com/prabhakarlab/Banksy. For in-depth guides to package 93 | functionality and use cases, refer to the package webpage at 94 | https://prabhakarlab.github.io/Banksy.

    95 |
    96 |
    97 |

    See also

    98 | 101 |
    102 |
    103 |

    Author

    104 |

    Maintainer: Joseph Lee joseph.lee@u.nus.edu (ORCID)

    105 |

    Authors:

    • Vipul Singhal

    • 106 |
    107 | 108 |
    109 | 112 |
    113 | 114 | 115 |
    118 | 119 |
    120 |

    Site built with pkgdown 2.0.7.

    121 |
    122 | 123 |
    124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /docs/reference/Rplot001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/reference/Rplot001.png -------------------------------------------------------------------------------- /docs/reference/clusterNames.html: -------------------------------------------------------------------------------- 1 | 2 | Get names of clustering runs. — clusterNames • Banksy 6 | 7 | 8 |
    9 |
    59 | 60 | 61 | 62 |
    63 |
    64 | 69 | 70 |
    71 |

    Get names of clustering runs.

    72 |
    73 | 74 |
    75 |
    clusterNames(se)
    76 |
    77 | 78 |
    79 |

    Arguments

    80 |
    se
    81 |

    A SpatialExperiment, 82 | SingleCellExperiment or SummarizedExperiment 83 | object with clusterBanksy ran.

    84 | 85 |
    86 |
    87 |

    Value

    88 | 89 | 90 |

    A character vector of names of clustering runs.

    91 |
    92 | 93 |
    94 |

    Examples

    95 |
    data(rings)
     96 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30))
     97 | #> Computing neighbors...
     98 | #> Spatial mode is kNN_median
     99 | #> Parameters: k_geom=15
    100 | #> Done
    101 | #> Computing neighbors...
    102 | #> Spatial mode is kNN_median
    103 | #> Parameters: k_geom=30
    104 | #> Done
    105 | #> Computing harmonic m = 0
    106 | #> Using 15 neighbors
    107 | #> Done
    108 | #> Computing harmonic m = 1
    109 | #> Using 30 neighbors
    110 | #> Centering
    111 | #> Done
    112 | spe <- runBanksyPCA(spe, M = 1, lambda = c(0, 0.2), npcs = 20)
    113 | spe <- clusterBanksy(spe, M = 1, lambda = c(0, 0.2), resolution = 1)
    114 | clusterNames(spe)
    115 | #> [1] "clust_M1_lam0_k50_res1"   "clust_M1_lam0.2_k50_res1"
    116 | 
    117 | 
    118 |
    119 |
    120 | 123 |
    124 | 125 | 126 |
    129 | 130 |
    131 |

    Site built with pkgdown 2.0.7.

    132 |
    133 | 134 |
    135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/reference/figures/README-unnamed-chunk-12-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-13-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/reference/figures/README-unnamed-chunk-13-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-14-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/reference/figures/README-unnamed-chunk-14-1.png -------------------------------------------------------------------------------- /docs/reference/figures/README-unnamed-chunk-15-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/reference/figures/README-unnamed-chunk-15-1.png -------------------------------------------------------------------------------- /docs/reference/hippocampus.html: -------------------------------------------------------------------------------- 1 | 2 | Mouse Hippocampus VeraFISH data — hippocampus • Banksy 10 | 11 | 12 |
    13 |
    63 | 64 | 65 | 66 |
    67 |
    68 | 73 | 74 |
    75 |

    This dataset comprises VeraFISH profiling of cells in the mouse hippocampus. 76 | Gene expression and cell centroids for 10,944 cells and 129 genes in 2 77 | spatial dimensions are provided. For details on how this dataset was 78 | generated, refer to Supplementary Information section 2.2 of our 79 | preprint.

    80 |
    81 | 82 |
    83 |
    data(hippocampus)
    84 |
    85 | 86 |
    87 |

    Format

    88 |

    A list with 2 entries:

    expression
    89 |

    (matrix) gene expression matrix

    90 | 91 |
    locations
    92 |

    (data.frame) cell centroids in 2D

    93 | 94 | 95 |
    96 |
    97 |

    Value

    98 | 99 | 100 |

    List with expression and locations

    101 |
    102 | 103 |
    104 | 107 |
    108 | 109 | 110 |
    113 | 114 |
    115 |

    Site built with pkgdown 2.0.7.

    116 |
    117 | 118 |
    119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | -------------------------------------------------------------------------------- /docs/reference/index.html: -------------------------------------------------------------------------------- 1 | 2 | Function reference • Banksy 6 | 7 | 8 |
    9 |
    59 | 60 | 61 | 62 |
    63 |
    64 | 67 | 68 | 72 | 75 | 76 | 79 | 80 | 84 | 87 | 88 | 91 | 92 | 96 | 99 | 100 | 103 | 104 | 107 | 108 | 111 | 112 | 115 | 116 | 120 | 123 | 124 | 127 | 128 | 132 | 135 | 136 |
    69 |

    Neighborhood matrix computation

    70 |

    71 |
    73 |

    computeBanksy()

    74 |

    Compute the component neighborhood matrices for the BANKSY matrix.

    77 |

    getBanksyMatrix()

    78 |

    Builds the BANKSY matrix from neighborhood matrices.

    81 |

    Dimensionality reduction

    82 |

    83 |
    85 |

    runBanksyPCA()

    86 |

    Run PCA on a BANKSY matrix.

    89 |

    runBanksyUMAP()

    90 |

    Run UMAP on a BANKSY embedding.

    93 |

    Clustering

    94 |

    95 |
    97 |

    clusterBanksy()

    98 |

    Perform clustering in BANKSY's neighborhood-augmented feature space.

    101 |

    connectClusters()

    102 |

    Relabel cluster labels across parameter runs to maximise their similarity.

    105 |

    compareClusters()

    106 |

    Compare cluster outputs based on various clustering comparison measures.

    109 |

    smoothLabels()

    110 |

    k-Nearest neighbor cluster label smoothing.

    113 |

    clusterNames()

    114 |

    Get names of clustering runs.

    117 |

    Datasets

    118 |

    119 |
    121 |

    hippocampus

    122 |

    Mouse Hippocampus VeraFISH data

    125 |

    rings

    126 |

    An unrealistic simulation of spatially-resolved omics data.

    129 |

    Misc.

    130 |

    131 |
    133 |

    simulateDataset()

    134 |

    Simulate an unrealistic spatial omics dataset.

    137 | 138 | 141 |
    142 | 143 | 144 |
    147 | 148 |
    149 |

    Site built with pkgdown 2.0.7.

    150 |
    151 | 152 |
    153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | -------------------------------------------------------------------------------- /docs/reference/rings.html: -------------------------------------------------------------------------------- 1 | 2 | An unrealistic simulation of spatially-resolved omics data. — rings • Banksy 7 | 8 | 9 |
    10 |
    60 | 61 | 62 | 63 |
    64 |
    65 | 70 | 71 |
    72 |

    This dataset comprises gene expression and spatial coordinates for 50 genes 73 | and 308 cells from 4 clusters (rings$clusters). See system.file('scripts/rings.R', package='Banksy') on how this dataset was generated.

    74 |
    75 | 76 |
    77 |
    data(rings)
    78 |
    79 | 80 |
    81 |

    Format

    82 |

    A SpatialExperiment object.

    83 |
    84 |
    85 |

    Value

    86 | 87 | 88 |

    A SpatialExperiment object

    89 |
    90 | 91 |
    92 | 95 |
    96 | 97 | 98 |
    101 | 102 |
    103 |

    Site built with pkgdown 2.0.7.

    104 |
    105 | 106 |
    107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /docs/reference/simulateDataset-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/docs/reference/simulateDataset-1.png -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | https://prabhakarlab.github.io/Banksy/404.html 5 | 6 | 7 | https://prabhakarlab.github.io/Banksy/LICENSE-text.html 8 | 9 | 10 | https://prabhakarlab.github.io/Banksy/articles/batch-correction.html 11 | 12 | 13 | https://prabhakarlab.github.io/Banksy/articles/domain-segment.html 14 | 15 | 16 | https://prabhakarlab.github.io/Banksy/articles/index.html 17 | 18 | 19 | https://prabhakarlab.github.io/Banksy/articles/multi-sample.html 20 | 21 | 22 | https://prabhakarlab.github.io/Banksy/articles/parameter-selection.html 23 | 24 | 25 | https://prabhakarlab.github.io/Banksy/authors.html 26 | 27 | 28 | https://prabhakarlab.github.io/Banksy/index.html 29 | 30 | 31 | https://prabhakarlab.github.io/Banksy/news/index.html 32 | 33 | 34 | https://prabhakarlab.github.io/Banksy/reference/Banksy-package.html 35 | 36 | 37 | https://prabhakarlab.github.io/Banksy/reference/clusterBanksy.html 38 | 39 | 40 | https://prabhakarlab.github.io/Banksy/reference/clusterNames.html 41 | 42 | 43 | https://prabhakarlab.github.io/Banksy/reference/compareClusters.html 44 | 45 | 46 | https://prabhakarlab.github.io/Banksy/reference/computeBanksy.html 47 | 48 | 49 | https://prabhakarlab.github.io/Banksy/reference/connectClusters.html 50 | 51 | 52 | https://prabhakarlab.github.io/Banksy/reference/getBanksyMatrix.html 53 | 54 | 55 | https://prabhakarlab.github.io/Banksy/reference/hippocampus.html 56 | 57 | 58 | https://prabhakarlab.github.io/Banksy/reference/index.html 59 | 60 | 61 | https://prabhakarlab.github.io/Banksy/reference/rings.html 62 | 63 | 64 | https://prabhakarlab.github.io/Banksy/reference/runBanksyPCA.html 65 | 66 | 67 | https://prabhakarlab.github.io/Banksy/reference/runBanksyUMAP.html 68 | 69 | 70 | https://prabhakarlab.github.io/Banksy/reference/simulateDataset.html 71 | 72 | 73 | https://prabhakarlab.github.io/Banksy/reference/smoothLabels.html 74 | 75 | 76 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite BANKSY in publications use:") 2 | 3 | citEntry( 4 | entry = "Article", 5 | title = "BANKSY: A Spatial Omics Algorithm that Unifies Cell Typing and Tissue Domain Segmentation", 6 | author = personList( 7 | as.person("Vipul Singhal"), 8 | as.person("Nigel Chou"), 9 | as.person("Joseph Lee"), 10 | as.person("Jinyue Liu"), 11 | as.person("Wan Kee Chock"), 12 | as.person("Li Lin"), 13 | as.person("Yun-Ching Chang"), 14 | as.person("Erica Teo"), 15 | as.person("Hwee Kuan Lee"), 16 | as.person("Kok Hao Chen"), 17 | as.person("Shyam Prabhakar")), 18 | journal = "bioRxiv", 19 | year = 2022, 20 | url = "https://www.biorxiv.org/content/10.1101/2022.04.14.488259", 21 | textVersion = paste( 22 | "Singhal, V., Chou, N., et al.", 23 | "BANKSY: A Spatial Omics Algorithm that Unifies Cell Typing and Tissue Domain Segmentation", 24 | "Preprint at bioRxiv https://doi.org/10.1101/2022.04.14.488259 (2022)" 25 | ) 26 | ) 27 | -------------------------------------------------------------------------------- /inst/extdata/STARmap.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/inst/extdata/STARmap.rds -------------------------------------------------------------------------------- /inst/script/rings.R: -------------------------------------------------------------------------------- 1 | 2 | set.seed(2023) 3 | rings <- simulateDataset(n_cells=300, n_rings=4, n_genes=50) 4 | -------------------------------------------------------------------------------- /man/Banksy-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/Banksy-package.R 3 | \docType{package} 4 | \name{Banksy-package} 5 | \alias{Banksy-package} 6 | \alias{Banksy} 7 | \title{The Banksy package} 8 | \description{ 9 | Banksy is a library and R package for network analysis. 10 | } 11 | \section{Description}{ 12 | 13 | Banksy is an R package that incorporates spatial information to cluster 14 | cells in a feature space (e.g. gene expression). To incorporate spatial 15 | information, BANKSY computes the mean neighborhood expression and azimuthal 16 | Gabor filters that capture gene expression gradients. These features are 17 | combined with the cell's own expression to embed cells in a 18 | neighbor-augmented product space which can then be clustered, allowing for 19 | accurate and spatially-aware cell typing and tissue domain segmentation. 20 | } 21 | 22 | \section{Details}{ 23 | 24 | For a quick start to the package, please refer to the GitHub page at 25 | \url{https://github.com/prabhakarlab/Banksy}. For in-depth guides to package 26 | functionality and use cases, refer to the package webpage at 27 | \url{https://prabhakarlab.github.io/Banksy}. 28 | } 29 | 30 | \seealso{ 31 | Useful links: 32 | \itemize{ 33 | \item \url{https://github.com/prabhakarlab/Banksy} 34 | \item Report bugs at \url{https://github.com/prabhakarlab/Banksy/issues} 35 | } 36 | 37 | } 38 | \author{ 39 | \strong{Maintainer}: Joseph Lee \email{joseph.lee@u.nus.edu} (\href{https://orcid.org/0000-0002-4983-4714}{ORCID}) 40 | 41 | Authors: 42 | \itemize{ 43 | \item Vipul Singhal 44 | } 45 | 46 | } 47 | \keyword{internal} 48 | -------------------------------------------------------------------------------- /man/clusterBanksy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cluster.R 3 | \name{clusterBanksy} 4 | \alias{clusterBanksy} 5 | \title{Perform clustering in BANKSY's neighborhood-augmented feature space.} 6 | \usage{ 7 | clusterBanksy( 8 | se, 9 | use_agf = FALSE, 10 | lambda = 0.2, 11 | use_pcs = TRUE, 12 | npcs = 20L, 13 | dimred = NULL, 14 | ndims = NULL, 15 | assay_name = NULL, 16 | group = NULL, 17 | algo = c("leiden", "louvain", "kmeans", "mclust"), 18 | k_neighbors = 50, 19 | resolution = 1, 20 | leiden.iter = -1, 21 | kmeans.centers = 5, 22 | mclust.G = 5, 23 | M = NULL, 24 | seed = NULL, 25 | ... 26 | ) 27 | } 28 | \arguments{ 29 | \item{se}{A \code{SpatialExperiment}, 30 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 31 | object with \code{computeBanksy} ran.} 32 | 33 | \item{use_agf}{A logical vector specifying whether to use the AGF for 34 | clustering.} 35 | 36 | \item{lambda}{A numeric vector in \eqn{\in [0,1]} specifying a spatial 37 | weighting parameter. Larger values (e.g. 0.8) incorporate more spatial 38 | neighborhood and find spatial domains, while smaller values (e.g. 0.2) 39 | perform spatial cell-typing.} 40 | 41 | \item{use_pcs}{A logical scalar specifying whether to cluster on PCs. If 42 | FALSE, runs on the BANKSY matrix.} 43 | 44 | \item{npcs}{An integer scalar specifying the number of principal components 45 | to use if \code{use_pcs} is TRUE.} 46 | 47 | \item{dimred}{A string scalar specifying the name of an existing 48 | dimensionality reduction result to use. Will overwrite \code{use_pcs} if 49 | supplied.} 50 | 51 | \item{ndims}{An integer scalar specifying the number of dimensions to use if 52 | \code{dimred} is supplied.} 53 | 54 | \item{assay_name}{A string scalar specifying the name of the assay used in 55 | \code{computeBanksy}.} 56 | 57 | \item{group}{A string scalar specifying a grouping variable for samples in 58 | \code{se}. This is used to scale the samples in each group separately.} 59 | 60 | \item{algo}{A string scalar specifying the clustering algorithm to use; one 61 | of leiden, louvain, mclust, kmeans.} 62 | 63 | \item{k_neighbors}{An integer vector specifying number of neighbors for 64 | constructing sNN (for louvain / leiden).} 65 | 66 | \item{resolution}{A numeric vector specifying resolution used for clustering 67 | (louvain / leiden).} 68 | 69 | \item{leiden.iter}{An integer scalar specifying the number of leiden 70 | iterations. For running till convergence, set to -1 (leiden).} 71 | 72 | \item{kmeans.centers}{An integer vector specifying the number of kmeans 73 | clusters (kmeans).} 74 | 75 | \item{mclust.G}{An integer vector specifying the number of mixture 76 | components (Mclust).} 77 | 78 | \item{M}{Advanced usage. An integer vector specifying the highest azimuthal 79 | Fourier harmonic to cluster with. If specified, overwrites the 80 | \code{use_agf} argument.} 81 | 82 | \item{seed}{Random seed for clustering. If not specified, no seed is set.} 83 | 84 | \item{...}{to pass to methods} 85 | } 86 | \value{ 87 | A SpatialExperiment / SingleCellExperiment / SummarizedExperiment 88 | object with cluster labels in \code{colData(se)}. 89 | } 90 | \description{ 91 | Perform clustering in BANKSY's neighborhood-augmented feature space. 92 | } 93 | \details{ 94 | This function performs clustering on the principal components computed on 95 | the BANKSY matrix, i.e., the BANKSY embedding. The PCA corresponding to the 96 | parameters \code{use_agf} and \code{lambda} must have been computed with 97 | \link[Banksy]{runBanksyPCA}. Clustering may also be performed directly on the 98 | BANKSY matrix with \code{use_pcs} set to \code{FALSE} (this is not 99 | recommended). 100 | 101 | Four clustering algorithms are implemented. 102 | \itemize{ 103 | \item{leiden: Leiden graph-based clustering. The arguments 104 | \code{k_neighbors} and \code{resolution} should be specified.} 105 | \item{louvain: Louvain graph-based clustering. The arguments 106 | \code{k_neighbors} and \code{resolution} should be specified.} 107 | \item{kmeans: kmeans clustering. The argument \code{kmeans.centers} should 108 | be specified.} 109 | \item{mclust: Gaussian mixture model-based clustering. The argument 110 | \code{mclust.G} should be specified.} 111 | } 112 | 113 | By default, no seed is set for clustering. If a seed is specified, the same 114 | seed is used for clustering across the input parameters. 115 | } 116 | \examples{ 117 | data(rings) 118 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 119 | spe <- runBanksyPCA(spe, M = 1, lambda = c(0, 0.2), npcs = 20) 120 | spe <- clusterBanksy(spe, M = 1, lambda = c(0, 0.2), resolution = 1) 121 | 122 | } 123 | -------------------------------------------------------------------------------- /man/clusterNames.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cluster.R 3 | \name{clusterNames} 4 | \alias{clusterNames} 5 | \title{Get names of clustering runs.} 6 | \usage{ 7 | clusterNames(se) 8 | } 9 | \arguments{ 10 | \item{se}{A \code{SpatialExperiment}, 11 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 12 | object with \code{clusterBanksy} ran.} 13 | } 14 | \value{ 15 | A character vector of names of clustering runs. 16 | } 17 | \description{ 18 | Get names of clustering runs. 19 | } 20 | \examples{ 21 | data(rings) 22 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 23 | spe <- runBanksyPCA(spe, M = 1, lambda = c(0, 0.2), npcs = 20) 24 | spe <- clusterBanksy(spe, M = 1, lambda = c(0, 0.2), resolution = 1) 25 | clusterNames(spe) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /man/compareClusters.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cluster.R 3 | \name{compareClusters} 4 | \alias{compareClusters} 5 | \title{Compare cluster outputs based on various clustering comparison measures.} 6 | \usage{ 7 | compareClusters( 8 | se, 9 | func = c("ARI", "AMI", "MARI", "MARIraw", "RI", "NID", "NMI", "NVI"), 10 | digits = 3 11 | ) 12 | } 13 | \arguments{ 14 | \item{se}{A \code{SpatialExperiment}, 15 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 16 | object with cluster labels in \code{colData(se)}.} 17 | 18 | \item{func}{A string scalar specifying what clustering comparison measure to 19 | compute. See \code{?aricode} for more information.} 20 | 21 | \item{digits}{An integer scalar specifying the number of digits to round to.} 22 | } 23 | \value{ 24 | A matrix of cluster comparison measures. 25 | } 26 | \description{ 27 | Compare cluster outputs based on various clustering comparison measures. 28 | } 29 | \examples{ 30 | data(rings) 31 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 32 | spe <- runBanksyPCA(spe, M = 1, lambda = 0.2, npcs = 20) 33 | spe <- clusterBanksy(spe, M = 1, lambda = 0.2, resolution = c(0.1, 1)) 34 | spe <- connectClusters(spe) 35 | compareClusters(spe) 36 | 37 | } 38 | -------------------------------------------------------------------------------- /man/computeBanksy.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/computation.R 3 | \name{computeBanksy} 4 | \alias{computeBanksy} 5 | \title{Compute the component neighborhood matrices for the BANKSY matrix.} 6 | \usage{ 7 | computeBanksy( 8 | se, 9 | assay_name, 10 | coord_names = NULL, 11 | compute_agf = FALSE, 12 | k_geom = 15, 13 | spatial_mode = c("kNN_median", "kNN_r", "kNN_rn", "kNN_rank", "kNN_unif", "rNN_gauss"), 14 | n = 2, 15 | sigma = 1.5, 16 | alpha = 0.05, 17 | k_spatial = 100L, 18 | M = NULL, 19 | sample_size = NULL, 20 | sample_renorm = TRUE, 21 | seed = NULL, 22 | dimensions = "all", 23 | center = TRUE, 24 | verbose = TRUE 25 | ) 26 | } 27 | \arguments{ 28 | \item{se}{A \code{SpatialExperiment}, 29 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 30 | object. If not a SpatialExperiment object, argument \code{coord_names} 31 | must be provided.} 32 | 33 | \item{assay_name}{A string scalar specifying the name of the assay to use.} 34 | 35 | \item{coord_names}{A string vector specifying the names in \code{colData} 36 | corresponding to spatial coordinates.} 37 | 38 | \item{compute_agf}{A logical scalar specifying whether to compute the AGF.} 39 | 40 | \item{k_geom}{An integer scalar specifying the number of neighbors to use. 41 | Values \eqn{\in [15,30]} work well.} 42 | 43 | \item{spatial_mode}{A string scalar specifying the kernel for neighborhood 44 | computation (default: kNN_median). 45 | \itemize{ 46 | \item{kNN_median: k-nearest neighbors with median-scaled Gaussian kernel} 47 | \item{kNN_r: k-nearest neighbors with $1/r$ kernel} 48 | \item{kNN_rn: k-nearest neighbors with $1/r^n$ kernel} 49 | \item{kNN_rank: k-nearest neighbors with rank Gaussian kernel} 50 | \item{kNN_unif: k-nearest neighbors wth uniform kernel} 51 | \item{rNN_gauss: radial nearest neighbors with Gaussian kernel} 52 | }} 53 | 54 | \item{n}{A numeric scalar specifying the exponent of radius (for kNN_rn).} 55 | 56 | \item{sigma}{A numeric scalar specifying the std. dev. of Gaussian kernel 57 | (for rNN_gauss).} 58 | 59 | \item{alpha}{A numeric scalar specifying the radius used: larger alphas give 60 | smaller radii (for rNN_gauss).} 61 | 62 | \item{k_spatial}{An integer scalar specifying the initial number of neighbors 63 | to use (for rNN_gauss)} 64 | 65 | \item{M}{Advanced usage. A integer scalar specifying the highest azimuthal 66 | Fourier harmonic to compute. If specified, overwrites the \code{use_agf} 67 | argument.} 68 | 69 | \item{sample_size}{An integer scalar number of neighbors to sample from the 70 | neighborhood.} 71 | 72 | \item{sample_renorm}{A logical scalar specifying whether to renormalize the 73 | neighbor weights to 1.} 74 | 75 | \item{seed}{An integer scalar specifying seed for sampling the neighborhood.} 76 | 77 | \item{dimensions}{A character vector specifying the dimensions to use when 78 | computing neighborhood. 79 | \itemize{ 80 | \item{subset of colnames of cell.locs} 81 | \item{all}{Uses all colnames of spatialCoords to compute (default)} 82 | }} 83 | 84 | \item{center}{A logical scalar specifying whether to center higher order 85 | harmonics in local neighborhoods.} 86 | 87 | \item{verbose}{A logical scalar specifying verbosity.} 88 | } 89 | \value{ 90 | A SpatialExperiment / SingleCellExperiment / SummarizedExperiment 91 | object with neighborhood matrices added. 92 | } 93 | \description{ 94 | Compute the component neighborhood matrices for the BANKSY matrix. 95 | } 96 | \details{ 97 | Given an expression matrix (as specified by \code{assay_name}), this function 98 | computes the mean neighborhood matrix (\code{H0}) and optionally, the 99 | azimuthal Gabor filter (AGF) matrix (\code{H1}). The number of neighbors 100 | used to define the spatial neighborhood is given by \code{k_geom}. 101 | Different kernels may be used to compute the neighborhood features, 102 | specified by \code{spatial_mode}. 103 | } 104 | \examples{ 105 | data(rings) 106 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 107 | 108 | } 109 | -------------------------------------------------------------------------------- /man/connectClusters.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cluster.R 3 | \name{connectClusters} 4 | \alias{connectClusters} 5 | \title{Relabel cluster labels across parameter runs to maximise their similarity.} 6 | \usage{ 7 | connectClusters(se, map_to = NULL, verbose = TRUE) 8 | } 9 | \arguments{ 10 | \item{se}{A \code{SpatialExperiment}, 11 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 12 | object with cluster labels in \code{colData(se)}.} 13 | 14 | \item{map_to}{A string scalar specify a cluster to map to.} 15 | 16 | \item{verbose}{A logical scalar specifying verbosity.} 17 | } 18 | \value{ 19 | A SpatialExperiment / SingleCellExperiment / SummarizedExperiment 20 | object with 'connected' cluster labels in \code{colData(se)}. 21 | } 22 | \description{ 23 | Relabel cluster labels across parameter runs to maximise their similarity. 24 | } 25 | \examples{ 26 | data(rings) 27 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 28 | spe <- runBanksyPCA(spe, M = 1, lambda = c(0, 0.2), npcs = 20) 29 | spe <- clusterBanksy(spe, M = 1, lambda = c(0, 0.2), resolution = 1) 30 | spe <- connectClusters(spe) 31 | 32 | } 33 | -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-12-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/man/figures/README-unnamed-chunk-12-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-13-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/man/figures/README-unnamed-chunk-13-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-14-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/man/figures/README-unnamed-chunk-14-1.png -------------------------------------------------------------------------------- /man/figures/README-unnamed-chunk-15-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/man/figures/README-unnamed-chunk-15-1.png -------------------------------------------------------------------------------- /man/getBanksyMatrix.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/computation.R 3 | \name{getBanksyMatrix} 4 | \alias{getBanksyMatrix} 5 | \title{Builds the BANKSY matrix from neighborhood matrices.} 6 | \usage{ 7 | getBanksyMatrix( 8 | se, 9 | M, 10 | lambda, 11 | assay_name = NULL, 12 | scale = FALSE, 13 | group = NULL, 14 | verbose = TRUE 15 | ) 16 | } 17 | \arguments{ 18 | \item{se}{A \code{SpatialExperiment}, 19 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 20 | object with \code{computeBanksy} ran.} 21 | 22 | \item{M}{A integer scalar specifying the highest azimuthal 23 | Fourier harmonic to compute.} 24 | 25 | \item{lambda}{A numeric vector in \eqn{\in [0,1]} specifying a spatial 26 | weighting parameter. Larger values (e.g. 0.8) incorporate more spatial 27 | neighborhood and find spatial domains, while smaller values (e.g. 0.2) 28 | perform spatial cell-typing.} 29 | 30 | \item{assay_name}{A string scalar specifying the name of the assay used in 31 | \code{computeBanksy}.} 32 | 33 | \item{scale}{A logical scalar specifying whether to scale the features to 34 | zero mean and unit standard deviation. This is performed before 35 | multiplying the assays by their corresponding lambda weighting factors.} 36 | 37 | \item{group}{A string scalar specifying a grouping variable for samples in 38 | \code{se}. This is used to scale the samples in each group separately.} 39 | 40 | \item{verbose}{A logical scalar specifying verbosity.} 41 | } 42 | \value{ 43 | BANKSY matrix. 44 | } 45 | \description{ 46 | Builds the BANKSY matrix from neighborhood matrices. 47 | } 48 | \details{ 49 | After computation of the neighborhood matrices 50 | (see \link[Banksy]{computeBanksy}), this function builds the BANKSY matrix by 51 | concatenating the original expression matrix with the neighborhood matrices, 52 | and scales each matrix by an appropriate weight as determined by 53 | \code{lambda}. The weights of the own expression matrix, mean neighborhood 54 | matrix and azimuthal Gabor filter are given by \eqn{\sqrt{1-\lambda}}, 55 | \eqn{\sqrt{\lambda/\mu}} and \eqn{\sqrt{\lambda/2\mu}} respectively, where 56 | \eqn{\mu=1.5}. In the case where the AGF is not computed, the weights for 57 | the own and mean neighborhood expression matrix simplify to 58 | \eqn{\sqrt{1-\lambda}} and \eqn{\sqrt{\lambda}} respectively. 59 | } 60 | \examples{ 61 | data(rings) 62 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 63 | banksyMatrix <- getBanksyMatrix(spe, M = 1, lambda = 0.2) 64 | 65 | } 66 | -------------------------------------------------------------------------------- /man/hippocampus.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{hippocampus} 5 | \alias{hippocampus} 6 | \title{Mouse Hippocampus VeraFISH data} 7 | \format{ 8 | A list with 2 entries: 9 | \describe{ 10 | \item{expression}{(matrix) gene expression matrix} 11 | \item{locations}{(data.frame) cell centroids in 2D} 12 | } 13 | } 14 | \usage{ 15 | data(hippocampus) 16 | } 17 | \value{ 18 | List with expression and locations 19 | } 20 | \description{ 21 | This dataset comprises VeraFISH profiling of cells in the mouse hippocampus. 22 | Gene expression and cell centroids for 10,944 cells and 129 genes in 2 23 | spatial dimensions are provided. For details on how this dataset was 24 | generated, refer to Supplementary Information section 2.2 of our 25 | \href{https://www.biorxiv.org/content/10.1101/2022.04.14.488259v1.supplementary-material}{preprint}. 26 | } 27 | \keyword{datasets} 28 | -------------------------------------------------------------------------------- /man/rings.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{rings} 5 | \alias{rings} 6 | \title{An unrealistic simulation of spatially-resolved omics data.} 7 | \format{ 8 | A SpatialExperiment object. 9 | } 10 | \usage{ 11 | data(rings) 12 | } 13 | \value{ 14 | A SpatialExperiment object 15 | } 16 | \description{ 17 | This dataset comprises gene expression and spatial coordinates for 50 genes 18 | and 308 cells from 4 clusters (\code{rings$clusters}). See \code{system.file('scripts/rings.R', package='Banksy')} on how this dataset was generated. 19 | } 20 | \keyword{datasets} 21 | -------------------------------------------------------------------------------- /man/runBanksyPCA.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/reduction.R 3 | \name{runBanksyPCA} 4 | \alias{runBanksyPCA} 5 | \title{Run PCA on a BANKSY matrix.} 6 | \usage{ 7 | runBanksyPCA( 8 | se, 9 | use_agf = FALSE, 10 | lambda = 0.2, 11 | npcs = 20L, 12 | assay_name = NULL, 13 | scale = TRUE, 14 | group = NULL, 15 | M = NULL, 16 | seed = NULL 17 | ) 18 | } 19 | \arguments{ 20 | \item{se}{A \code{SpatialExperiment}, 21 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 22 | object with \code{computeBanksy} ran.} 23 | 24 | \item{use_agf}{A logical vector specifying whether to use the AGF for 25 | computing principal components.} 26 | 27 | \item{lambda}{A numeric vector in \eqn{\in [0,1]} specifying a spatial 28 | weighting parameter. Larger values (e.g. 0.8) incorporate more spatial 29 | neighborhood and find spatial domains, while smaller values (e.g. 0.2) 30 | perform spatial cell-typing.} 31 | 32 | \item{npcs}{An integer scalar specifying the number of principal components 33 | to compute.} 34 | 35 | \item{assay_name}{A string scalar specifying the name of the assay used in 36 | \code{computeBanksy}.} 37 | 38 | \item{scale}{A logical scalar specifying whether to scale features before 39 | PCA. Defaults to TRUE.} 40 | 41 | \item{group}{A string scalar specifying a grouping variable for samples in 42 | \code{se}. This is used to scale the samples in each group separately.} 43 | 44 | \item{M}{Advanced usage. An integer vector specifying the highest azimuthal 45 | Fourier harmonic to use. If specified, overwrites the \code{use_agf} 46 | argument.} 47 | 48 | \item{seed}{Seed for PCA. If not specified, no seed is set.} 49 | } 50 | \value{ 51 | A SpatialExperiment / SingleCellExperiment / SummarizedExperiment 52 | object with PC coordinates in \code{reducedDims(se)}. 53 | } 54 | \description{ 55 | Run PCA on a BANKSY matrix. 56 | } 57 | \details{ 58 | This function runs PCA on the BANKSY matrix 59 | (see \link[Banksy]{getBanksyMatrix}) with features scaled to zero mean and 60 | unit standard deviation. 61 | } 62 | \examples{ 63 | data(rings) 64 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 65 | spe <- runBanksyPCA(spe, M = 1, lambda = 0.2, npcs = 20) 66 | 67 | } 68 | -------------------------------------------------------------------------------- /man/runBanksyUMAP.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/reduction.R 3 | \name{runBanksyUMAP} 4 | \alias{runBanksyUMAP} 5 | \title{Run UMAP on a BANKSY embedding.} 6 | \usage{ 7 | runBanksyUMAP( 8 | se, 9 | use_agf = FALSE, 10 | lambda = 0.2, 11 | use_pcs = TRUE, 12 | npcs = 20L, 13 | dimred = NULL, 14 | ndims = NULL, 15 | assay_name = NULL, 16 | scale = TRUE, 17 | group = NULL, 18 | n_neighbors = 30L, 19 | spread = 3, 20 | min_dist = 0.1, 21 | n_epochs = 300L, 22 | M = NULL, 23 | seed = NULL, 24 | ... 25 | ) 26 | } 27 | \arguments{ 28 | \item{se}{A \code{SpatialExperiment}, 29 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 30 | object with \code{computeBanksy} ran.} 31 | 32 | \item{use_agf}{A logical vector specifying whether to use the AGF for 33 | computing UMAP.} 34 | 35 | \item{lambda}{A numeric vector in \eqn{\in [0,1]} specifying a spatial 36 | weighting parameter. Larger values (e.g. 0.8) incorporate more spatial 37 | neighborhood and find spatial domains, while smaller values (e.g. 0.2) 38 | perform spatial cell-typing.} 39 | 40 | \item{use_pcs}{A logical scalar specifying whether to run UMAP on PCs. If 41 | FALSE, runs on the BANKSY matrix.} 42 | 43 | \item{npcs}{An integer scalar specifying the number of principal components 44 | to use if \code{use_pcs} is TRUE.} 45 | 46 | \item{dimred}{A string scalar specifying the name of an existing 47 | dimensionality reduction result to use. Will overwrite \code{use_pcs} if 48 | supplied.} 49 | 50 | \item{ndims}{An integer scalar specifying the number of dimensions to use if 51 | \code{dimred} is supplied.} 52 | 53 | \item{assay_name}{A string scalar specifying the name of the assay used in 54 | \code{computeBanksy}.} 55 | 56 | \item{scale}{A logical scalar specifying whether to scale features before 57 | UMAP. Only used when use_pcs is FALSE. Defaults to TRUE.} 58 | 59 | \item{group}{A string scalar specifying a grouping variable for samples in 60 | \code{se}. This is used to scale the samples in each group separately.} 61 | 62 | \item{n_neighbors}{An integer scalar specifying the number of neighbors to 63 | use for UMAP.} 64 | 65 | \item{spread}{A numeric scalar specifying the effective scale of embedded 66 | points.} 67 | 68 | \item{min_dist}{A numeric scalar specifying the effective min. dist. between 69 | embedded points.} 70 | 71 | \item{n_epochs}{An integer scalar specifying the number of epochs to run 72 | UMAP optimization.} 73 | 74 | \item{M}{Advanced usage. An integer vector specifying the highest azimuthal 75 | Fourier harmonic to use. If specified, overwrites the \code{use_agf} 76 | argument.} 77 | 78 | \item{seed}{Seed for UMAP. If not specified, no seed is set.} 79 | 80 | \item{...}{parameters to pass to uwot::umap} 81 | } 82 | \value{ 83 | A SpatialExperiment / SingleCellExperiment / SummarizedExperiment 84 | object with UMAP coordinates in \code{reducedDims(se)}. 85 | } 86 | \description{ 87 | Run UMAP on a BANKSY embedding. 88 | } 89 | \details{ 90 | This function runs UMAP on the principal components computed on the 91 | BANKSY matrix. 92 | } 93 | \examples{ 94 | data(rings) 95 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 96 | spe <- runBanksyPCA(spe, M = 1, lambda = 0.2, npcs = 20) 97 | spe <- runBanksyUMAP(spe, M = 1, lambda = 0.2) 98 | 99 | } 100 | -------------------------------------------------------------------------------- /man/simulateDataset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/misc.R 3 | \name{simulateDataset} 4 | \alias{simulateDataset} 5 | \title{Simulate an unrealistic spatial omics dataset.} 6 | \usage{ 7 | simulateDataset(n_cells = 300, n_genes = 30, n_rings = 3, rate = 10) 8 | } 9 | \arguments{ 10 | \item{n_cells}{An integer scalar specifying the approximate number of cells.} 11 | 12 | \item{n_genes}{An integer scalar specifying the number of genes.} 13 | 14 | \item{n_rings}{An integer scalar specifying the number of spatial rings.} 15 | 16 | \item{rate}{A numeric scalar specifying the Poisson rate parameter for 17 | simulating counts.} 18 | } 19 | \value{ 20 | A SpatialExperiment object. 21 | } 22 | \description{ 23 | Simulate an unrealistic spatial omics dataset. 24 | } 25 | \details{ 26 | This function generates an unrealistic spatial omics dataset based on a 27 | user-specified number of cells and genes. The number of clusters is defined 28 | by \code{n_rings}, while counts follow a Poisson distribution with a 29 | user-specified rate \code{rate}. The simulation is set up such that the 30 | number of cells in each cluster is uniformly distributed; as such, the final 31 | number of cells is approximately equal to the user-specified number of cells. 32 | } 33 | \examples{ 34 | set.seed(2023) 35 | rings <- simulateDataset(n_cells = 5e3, n_genes = 50, n_rings = 8) 36 | rings 37 | table(rings$cluster) 38 | df <- cbind.data.frame( 39 | SummarizedExperiment::colData(rings), 40 | SpatialExperiment::spatialCoords(rings)) 41 | library(ggplot2) 42 | ggplot(df, aes(x=x, y=y, col=cluster)) + geom_point() + theme_classic() 43 | 44 | } 45 | -------------------------------------------------------------------------------- /man/smoothLabels.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/cluster.R 3 | \name{smoothLabels} 4 | \alias{smoothLabels} 5 | \title{k-Nearest neighbor cluster label smoothing.} 6 | \usage{ 7 | smoothLabels( 8 | se, 9 | cluster_names = NULL, 10 | coord_names = NULL, 11 | k = 15L, 12 | prop_thres = 0.5, 13 | max_iter = 10, 14 | verbose = TRUE 15 | ) 16 | } 17 | \arguments{ 18 | \item{se}{A \code{SpatialExperiment}, 19 | \code{SingleCellExperiment} or \code{SummarizedExperiment} 20 | object with cluster labels in \code{colData(se)}.} 21 | 22 | \item{cluster_names}{A string vector of label names to smooth. If NULL, 23 | smooths labels in colData(se) matching /^clust/} 24 | 25 | \item{coord_names}{A string vector specifying the names in \code{colData} 26 | corresponding to spatial coordinates.} 27 | 28 | \item{k}{An integer scalar specifying number of neighbors for smooething.} 29 | 30 | \item{prop_thres}{A numeric scalar \eqn{\in [0,1]} specifying a label 31 | proportions threshold If the fraction of neighbors with a certain label 32 | exceeds this proportion, change the label of the current sample 33 | (default: 0.5).} 34 | 35 | \item{max_iter}{An integer scalar specifying the max number of smoothing 36 | iterations. Set to -1 for smoothing to convergence.} 37 | 38 | \item{verbose}{A logical scalar specifying verbosity.} 39 | } 40 | \value{ 41 | A SpatialExperiment / SingleCellExperiment / SummarizedExperiment 42 | object with smoothed cluster labels in \code{colData(se)} suffixed with 43 | '_smooth'. 44 | } 45 | \description{ 46 | k-Nearest neighbor cluster label smoothing. 47 | } 48 | \details{ 49 | As described in SpiceMix (https://doi.org/10.1038/s41588-022-01256-z). 50 | Implemented for labels that can be coerced to numeric only. 51 | } 52 | \examples{ 53 | data(rings) 54 | spe <- computeBanksy(rings, assay_name = "counts", M = 1, k_geom = c(15, 30)) 55 | spe <- runBanksyPCA(spe, M = 1, lambda = 0.2, npcs = 20) 56 | spe <- clusterBanksy(spe, M = 1, lambda = 0.2, resolution = 1) 57 | spe <- smoothLabels(spe, cluster_names = "clust_M1_lam0.2_k50_res1") 58 | 59 | } 60 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | # This file is part of the standard setup for testthat. 2 | # It is recommended that you do not modify it. 3 | # 4 | # Where should you do additional test configuration? 5 | # Learn more about the roles of various files in: 6 | # * https://r-pkgs.org/tests.html 7 | # * https://testthat.r-lib.org/reference/test_package.html#special-files 8 | 9 | library(testthat) 10 | library(Banksy) 11 | 12 | test_check("Banksy") 13 | -------------------------------------------------------------------------------- /tests/testthat/test-cluster.R: -------------------------------------------------------------------------------- 1 | library(SummarizedExperiment) 2 | library(SingleCellExperiment) 3 | library(SpatialExperiment) 4 | 5 | set.seed(1000) 6 | spe <- simulateDataset(rate = 2) 7 | spe <- computeBanksy(spe, assay_name = "counts", compute_agf = TRUE) 8 | spe <- runBanksyPCA(spe, use_agf = TRUE, seed = 1000) 9 | 10 | test_that("clusterBanksy with invalid algo", { 11 | expect_error(clusterBanksy(spe, algo = "?")) 12 | }) 13 | 14 | test_that("clusterBanksy with leiden specifies correct args", { 15 | expect_error(clusterBanksy(spe, k_neighbors = NULL)) 16 | expect_error(clusterBanksy(spe, resolution = NULL)) 17 | }) 18 | 19 | test_that("clusterBanksy gives message when seeded", { 20 | expect_message(clusterBanksy(spe, use_agf = TRUE, seed = 1000)) 21 | }) 22 | 23 | test_that("clusterBanksy gives expected output", { 24 | spe1 <- clusterBanksy(spe, use_agf = TRUE, use_pcs = TRUE, seed = 1000) 25 | expect_equal(length(clusterNames(spe1)), 1) 26 | spe2 <- clusterBanksy(spe, use_agf = TRUE, use_pcs = FALSE, seed = 1000) 27 | expect_equal(length(clusterNames(spe2)), 1) 28 | }) 29 | 30 | spe <- clusterBanksy(spe, use_agf = TRUE, resolution = 1, seed = 1000) 31 | 32 | test_that("connectClusters with invalid map_to", { 33 | expect_error(connectClusters(spe, map_to = "?")) 34 | }) 35 | 36 | test_that("connectClusters gives expected output", { 37 | cnm <- tail(colnames(colData(spe)), n = 1) 38 | 39 | before <- sum(spe$cluster == colData(spe)[, cnm]) 40 | 41 | spe_connect <- connectClusters(spe) 42 | after <- sum(spe_connect$cluster == colData(spe_connect)[, cnm]) 43 | expect_gte(after, before) 44 | 45 | spe_connect <- connectClusters(spe, map_to = cnm) 46 | after <- sum(spe_connect$cluster == colData(spe_connect)[, cnm]) 47 | expect_gte(after, before) 48 | }) 49 | 50 | test_that("smoothLabels with invalid cluster_names", { 51 | expect_error(smoothLabels(spe, cluster_names = "?")) 52 | }) 53 | 54 | test_that("smoothLabels with invalid cluster_names", { 55 | data(rings) 56 | rings$cluster <- NULL 57 | expect_error(smoothLabels(rings)) 58 | }) 59 | 60 | test_that("smoothLabels with gives expected output", { 61 | cnm <- tail(colnames(colData(spe)), n = 1) 62 | spe <- smoothLabels(spe, cnm) 63 | expect_true(any(grepl("smooth", colnames(colData(spe))))) 64 | }) 65 | 66 | test_that("compareClusters with no clusters", { 67 | spe$cluster <- NULL 68 | expect_error(compareClusters(spe)) 69 | }) 70 | 71 | test_that("compareClusters gives expected output", { 72 | cnm <- tail(colnames(colData(spe)), n = 1) 73 | expect_true(is.numeric( 74 | compareClusters(spe, func = c("ARI", "NMI")) 75 | )) 76 | }) 77 | -------------------------------------------------------------------------------- /tests/testthat/test-computation.R: -------------------------------------------------------------------------------- 1 | # Test funcs. in computation.R 2 | 3 | library(SummarizedExperiment) 4 | library(SingleCellExperiment) 5 | library(SpatialExperiment) 6 | 7 | data(rings) 8 | spe <- rings 9 | sce <- SingleCellExperiment(spe) 10 | assay(sce) <- NULL 11 | assay(sce, "counts") <- assay(spe, "counts") 12 | colData(sce) <- cbind(colData(spe), spatialCoords(spe)) 13 | 14 | test_that("computeBanksy without assay_name", { 15 | expect_error( 16 | computeBanksy(spe) 17 | ) 18 | }) 19 | 20 | test_that("computeBanksy with M and k_geom mismatch", { 21 | expect_error( 22 | computeBanksy(spe, assay_name = "counts", M = 1, k_geom = c(15, 30, 60)) 23 | ) 24 | }) 25 | 26 | test_that("computeBanksy with invalid assay_name", { 27 | expect_error( 28 | computeBanksy(spe, assay_name = "hello") 29 | ) 30 | }) 31 | 32 | test_that("computeBanksy with invalid assay_name", { 33 | expect_error( 34 | computeBanksy(spe, assay_name = "?") 35 | ) 36 | }) 37 | 38 | test_that("computeBanksy on SPE without spatial coords", { 39 | spatialCoords(spe) <- NULL 40 | expect_error( 41 | computeBanksy(spe, assay_name = "counts") 42 | ) 43 | }) 44 | 45 | test_that("computeBanksy on SCE without coord_names", { 46 | expect_error( 47 | computeBanksy(sce, assay_name = "counts") 48 | ) 49 | }) 50 | 51 | test_that("computeBanksy on SCE with invalid coord_names", { 52 | expect_error( 53 | computeBanksy(sce, assay_name = "counts", coord_names = c("x", "?")) 54 | ) 55 | }) 56 | 57 | test_that("computeNeighbors with invalid spatial mode", { 58 | expect_error( 59 | computeBanksy(spe, assay_name = "counts", spatial_mode = "?") 60 | ) 61 | }) 62 | 63 | test_that("computeBanksy with spatial mode kNN_median", { 64 | spe <- computeBanksy(spe, compute_agf = TRUE, 65 | assay_name = "counts", spatial_mode = "kNN_median") 66 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 67 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 68 | 69 | expect_equal(metadata(spe)$BANKSY_params$assay_name, "counts") 70 | expect_equal(metadata(spe)$BANKSY_params$M, c(0, 1)) 71 | expect_equal(metadata(spe)$BANKSY_params$k_geom, c(15, 15)) 72 | expect_equal(metadata(spe)$BANKSY_params$spatial_mode, "kNN_median") 73 | 74 | sce <- computeBanksy(sce, compute_agf = TRUE, 75 | assay_name = "counts", spatial_mode = "kNN_median", 76 | coord_names = c("x", "y") 77 | ) 78 | expect_equal(dim(assay(sce, "H0")), dim(sce)) 79 | expect_equal(dim(assay(sce, "H1")), dim(sce)) 80 | }) 81 | 82 | test_that("computeBanksy with subsampling", { 83 | spe <- computeBanksy(spe, compute_agf = TRUE, 84 | assay_name = "counts", spatial_mode = "kNN_median", 85 | k_geom = 30, sample_size = 15, sample_renorm = TRUE, 86 | seed = 1000 87 | ) 88 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 89 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 90 | }) 91 | 92 | test_that("computeBanksy with spatial mode kNN_median with XL k_geom", { 93 | expect_error( 94 | computeBanksy(spe, 95 | assay_name = "counts", 96 | spatial_mode = "kNN_median", k_geom = ncol(spe) + 1 97 | ) 98 | ) 99 | }) 100 | 101 | test_that("computeBanksy with spatial_mode kNN_unif", { 102 | spe <- computeBanksy(spe, compute_agf = TRUE, 103 | assay_name = "counts", spatial_mode = "kNN_unif") 104 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 105 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 106 | }) 107 | 108 | test_that("computeBanksy with spatial mode kNN_unif with XL k_geom", { 109 | expect_error( 110 | computeBanksy(spe, 111 | assay_name = "counts", 112 | spatial_mode = "kNN_unif", k_geom = ncol(spe) + 1 113 | ) 114 | ) 115 | }) 116 | 117 | test_that("computeBanksy with spatial_mode kNN_rn", { 118 | spe <- computeBanksy(spe, compute_agf = TRUE, 119 | assay_name = "counts", spatial_mode = "kNN_rn") 120 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 121 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 122 | }) 123 | 124 | test_that("computeBanksy with spatial mode kNN_rn with XL k_geom", { 125 | expect_error( 126 | computeBanksy(spe, 127 | assay_name = "counts", 128 | spatial_mode = "kNN_rn", k_geom = ncol(spe) + 1 129 | ) 130 | ) 131 | }) 132 | 133 | test_that("computeBanksy with spatial_mode kNN_r", { 134 | spe <- computeBanksy(spe, compute_agf = TRUE, 135 | assay_name = "counts", spatial_mode = "kNN_r") 136 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 137 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 138 | }) 139 | 140 | test_that("computeBanksy with spatial mode kNN_r with XL k_geom", { 141 | expect_error( 142 | computeBanksy(spe, 143 | assay_name = "counts", 144 | spatial_mode = "kNN_r", k_geom = ncol(spe) + 1 145 | ) 146 | ) 147 | }) 148 | 149 | test_that("computeBanksy with spatial_mode kNN_rank", { 150 | spe <- computeBanksy(spe, compute_agf = TRUE, 151 | assay_name = "counts", spatial_mode = "kNN_rank") 152 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 153 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 154 | }) 155 | 156 | test_that("computeBanksy with spatial mode kNN_rank with XL k_geom", { 157 | expect_error( 158 | computeBanksy(spe, 159 | assay_name = "counts", 160 | spatial_mode = "kNN_rank", k_geom = ncol(spe) + 1 161 | ) 162 | ) 163 | }) 164 | 165 | test_that("computeBanksy with spatial_mode rNN_gauss", { 166 | spe <- computeBanksy(spe, compute_agf = TRUE, 167 | assay_name = "counts", spatial_mode = "rNN_gauss") 168 | expect_equal(dim(assay(spe, "H0")), dim(spe)) 169 | expect_equal(dim(assay(spe, "H1")), dim(spe)) 170 | }) 171 | 172 | test_that("computeBanksy with spatial mode rNN_gauss with XL k_spatial", { 173 | expect_error( 174 | computeBanksy(spe, 175 | assay_name = "counts", 176 | spatial_mode = "rNN_gauss", k_spatial = ncol(spe) + 1 177 | ) 178 | ) 179 | }) 180 | 181 | test_that("getBanksyMatrix without computeBanksy", { 182 | expect_error( 183 | getBanksyMatrix(spe, M = 1, lambda = 0.2) 184 | ) 185 | }) 186 | 187 | test_that("getBanksyMatrix", { 188 | spe <- computeBanksy(spe, compute_agf = TRUE, assay_name = "counts") 189 | 190 | dim_B0 <- c(nrow(spe) * 2, ncol(spe)) 191 | expect_equal(dim(getBanksyMatrix(spe, M = 0, lambda = 0.2)), dim_B0) 192 | 193 | dim_B1 <- c(nrow(spe) * 3, ncol(spe)) 194 | expect_equal(dim(getBanksyMatrix(spe, M = 1, lambda = 0.2)), dim_B1) 195 | 196 | dim_B0 <- c(nrow(spe) * 2, ncol(spe)) 197 | expect_equal(dim(getBanksyMatrix(spe, M = 0, lambda = 0.2, scale = TRUE)), dim_B0) 198 | 199 | dim_B1 <- c(nrow(spe) * 3, ncol(spe)) 200 | expect_equal(dim(getBanksyMatrix(spe, M = 1, lambda = 0.2, scale = TRUE)), dim_B1) 201 | 202 | expect_equal( 203 | as.numeric(rowMeans(getBanksyMatrix( 204 | spe, M = 1, lambda = 0.2, scale = TRUE))), 205 | rep(0, nrow(spe) * 3) 206 | ) 207 | 208 | mat <- getBanksyMatrix(spe, M = 0, lambda = 0) 209 | expect_equal(unique(tail(rowMeans(mat), nrow(spe))), 0) 210 | 211 | mat <- getBanksyMatrix(spe, M = 0, lambda = 1) 212 | expect_equal(unique(head(rowMeans(mat), nrow(spe))), 0) 213 | }) 214 | 215 | test_that("getBanksyMatrix multi-sample", { 216 | spe <- computeBanksy(spe, "counts", compute_agf = TRUE) 217 | 218 | expect_error(getBanksyMatrix( 219 | spe, 220 | M = 1, lambda = 0.2, scale = TRUE, group = "?" 221 | )) 222 | 223 | expect_equal( 224 | as.numeric(rowMeans(getBanksyMatrix( 225 | spe, 226 | M = 1, lambda = 0.2, scale = TRUE, group = "cluster" 227 | ))), 228 | rep(0, nrow(spe) * 3) 229 | ) 230 | 231 | rmeans <- as.numeric(rowMeans(getBanksyMatrix( 232 | spe, 233 | M = 1, lambda = 0.2, scale = TRUE, group = "cluster" 234 | ))) 235 | 236 | expect_equal( 237 | rmeans[seq(nrow(spe))], 238 | rep(0, nrow(spe)) 239 | ) 240 | expect_equal( 241 | rmeans[seq(nrow(spe) + 1, 2 * nrow(spe))], 242 | rep(0, nrow(spe)) 243 | ) 244 | }) 245 | -------------------------------------------------------------------------------- /tests/testthat/test-misc.R: -------------------------------------------------------------------------------- 1 | # Test funcs. in misc.R 2 | 3 | test_that("simulateDataset gives expected output", { 4 | expect_equal(nrow(simulateDataset(n_genes = 30)), 30) 5 | expect_equal(nlevels(simulateDataset(n_rings = 4)$cluster), 4) 6 | }) 7 | -------------------------------------------------------------------------------- /tests/testthat/test-reduction.R: -------------------------------------------------------------------------------- 1 | # Test funcs. in reduction.R 2 | 3 | library(SummarizedExperiment) 4 | library(SingleCellExperiment) 5 | library(SpatialExperiment) 6 | 7 | data(rings) 8 | spe <- rings 9 | spe <- computeBanksy(spe, assay_name = "counts", compute_agf = TRUE) 10 | 11 | test_that("runBanksyPCA gives message when seeded", { 12 | expect_message(runBanksyPCA(spe, use_agf = TRUE, seed = 1000)) 13 | }) 14 | 15 | test_that("runBanksyPCA gives expected output", { 16 | spe <- runBanksyPCA(spe, use_agf = TRUE) 17 | expect_equal(dim(reducedDim(spe)), c(ncol(spe), 20)) 18 | expect_in("percentVar", names(attributes(reducedDim(spe)))) 19 | }) 20 | 21 | 22 | test_that("runBanksyUMAP without PCs computed", { 23 | expect_error(runBanksyUMAP(spe, use_agf = TRUE, use_pcs = TRUE)) 24 | }) 25 | 26 | test_that("runBanksyUMAP requesting too many PCs", { 27 | spe <- runBanksyPCA(spe, use_agf = TRUE) 28 | expect_error(runBanksyUMAP(spe, use_agf = TRUE, use_pcs = TRUE, npcs = 50)) 29 | }) 30 | 31 | 32 | test_that("runBanksyUMAP gives expected output", { 33 | spe <- runBanksyPCA(spe, use_agf = TRUE) 34 | spe <- runBanksyUMAP(spe, use_agf = TRUE, use_pcs = TRUE) 35 | expect_equal(dim(reducedDim(spe, "UMAP_M1_lam0.2")), c(ncol(spe), 2)) 36 | 37 | spe <- runBanksyUMAP(spe, use_agf = TRUE, use_pcs = FALSE) 38 | expect_equal(dim(reducedDim(spe, "UMAP_M1_lam0.2")), c(ncol(spe), 2)) 39 | }) 40 | 41 | test_that("runBanksyUMAP gives message when seed", { 42 | spe <- runBanksyPCA(spe, use_agf = TRUE) 43 | expect_message(runBanksyUMAP(spe, use_agf = TRUE, 44 | use_pcs = TRUE, seed = 1000)) 45 | }) 46 | -------------------------------------------------------------------------------- /vignettes/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | *.R 3 | -------------------------------------------------------------------------------- /vignettes/batch-correction.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Spatial data integration with Harmony (10x Visium Human DLPFC)" 3 | output: BiocStyle::html_document 4 | vignette: > 5 | %\VignetteIndexEntry{Spatial data integration with Harmony (10x Visium Human DLPFC)} 6 | %\VignetteEngine{knitr::rmarkdown} 7 | %\VignetteEncoding{UTF-8} 8 | --- 9 | 10 | ```{r, include = FALSE} 11 | knitr::opts_chunk$set( 12 | collapse = TRUE, 13 | comment = "#>", 14 | fig.path = "figures/", 15 | dpi = 36 16 | ) 17 | ``` 18 | 19 | Here, we demonstrate how BANKSY can be used with Harmony for integrating 20 | multiple spatial omics datasets in the presence of strong batch effects. We use 21 | 10x Visium data of the human dorsolateral prefrontal cortex from Maynard et al 22 | (2018). The data comprise 12 samples obtained from 3 subjects, with manual 23 | annotation of the layers in each sample. 24 | 25 | ```{r, eval=TRUE, include=FALSE} 26 | start.time <- Sys.time() 27 | ``` 28 | 29 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 30 | library(Banksy) 31 | library(SummarizedExperiment) 32 | library(SpatialExperiment) 33 | library(Seurat) 34 | library(scran) 35 | library(data.table) 36 | library(harmony) 37 | 38 | library(scater) 39 | library(cowplot) 40 | library(ggplot2) 41 | 42 | SEED <- 1000 43 | ``` 44 | 45 | # Loading the data 46 | 47 | We fetch the data for all 12 DLPFC samples with the 48 | [*spatialLIBD*](https://bioconductor.org/packages/release/data/experiment/html/spatialLIBD.html) 49 | package. This might take awhile. 50 | 51 | ```{r, eval=T, message=FALSE, warning=FALSE} 52 | library(spatialLIBD) 53 | library(ExperimentHub) 54 | 55 | ehub <- ExperimentHub::ExperimentHub() 56 | spe <- spatialLIBD::fetch_data(type = "spe", eh = ehub) 57 | ``` 58 | 59 | After the download is completed, we trim the *SpatialExperiment* object, 60 | retaining only the counts and some metadata such as the sample identifier and 61 | pathology annotations. This saves some memory. 62 | 63 | ```{r, eval=T, message=FALSE, warning=FALSE} 64 | #' Remove NA spots 65 | na_id <- which(is.na(spe$layer_guess_reordered_short)) 66 | spe <- spe[, -na_id] 67 | 68 | #' Trim 69 | imgData(spe) <- NULL 70 | assay(spe, "logcounts") <- NULL 71 | reducedDims(spe) <- NULL 72 | rowData(spe) <- NULL 73 | colData(spe) <- DataFrame( 74 | sample_id = spe$sample_id, 75 | subject_id = factor(spe$sample_id, labels = rep(paste0("Subject", 1:3), each = 4)), 76 | clust_annotation = factor(as.numeric(spe$layer_guess_reordered_short)), 77 | in_tissue = spe$in_tissue, 78 | row.names = colnames(spe) 79 | ) 80 | colnames(spe) <- paste0(colnames(spe), "_", spe$sample_id) 81 | invisible(gc()) 82 | ``` 83 | 84 | We analyse the first sample of each subject due to vignette runtime constraints. 85 | 86 | ```{r, eval=T, message=FALSE, warning=FALSE} 87 | spe <- spe[, spe$sample_id %in% c("151507", "151669", "151673")] 88 | sample_names <- unique(spe$sample_id) 89 | ``` 90 | 91 | Next, stagger the spatial coordinates across the samples so that spots from 92 | different samples do not overlap. 93 | 94 | ```{r, eval=T, message=FALSE, warning=FALSE} 95 | #' Stagger spatial coordinates 96 | locs <- spatialCoords(spe) 97 | locs <- cbind(locs, sample_id = factor(spe$sample_id)) 98 | locs_dt <- data.table(locs) 99 | colnames(locs_dt) <- c("sdimx", "sdimy", "group") 100 | locs_dt[, sdimx := sdimx - min(sdimx), by = group] 101 | global_max <- max(locs_dt$sdimx) * 1.5 102 | locs_dt[, sdimx := sdimx + group * global_max] 103 | locs <- as.matrix(locs_dt[, 1:2]) 104 | rownames(locs) <- colnames(spe) 105 | spatialCoords(spe) <- locs 106 | ``` 107 | 108 | # Data preprocessing 109 | 110 | Find highly variable features and normalize counts. Here we use Seurat, but 111 | other methods may also be used (e.g. `scran::getTopHVGs`). 112 | 113 | ```{r, eval=T, message=FALSE, warning=FALSE} 114 | #' Get HVGs 115 | seu <- as.Seurat(spe, data = NULL) 116 | seu <- FindVariableFeatures(seu, nfeatures = 2000) 117 | 118 | #' Normalize data 119 | scale_factor <- median(colSums(assay(spe, "counts"))) 120 | seu <- NormalizeData(seu, scale.factor = scale_factor, normalization.method = "RC") 121 | 122 | #' Add data to SpatialExperiment and subset to HVGs 123 | aname <- "normcounts" 124 | assay(spe, aname) <- GetAssayData(seu) 125 | spe <- spe[VariableFeatures(seu),] 126 | ``` 127 | 128 | # Running BANKSY 129 | 130 | Compute BANKSY neighborhood matrices. We use `k_geom=18` corresponding to 131 | first and second-order neighbors in 10x Visium. 132 | 133 | ```{r, eval=T, message=FALSE, warning=FALSE} 134 | compute_agf <- TRUE 135 | k_geom <- 18 136 | spe <- computeBanksy(spe, assay_name = aname, compute_agf = compute_agf, k_geom = k_geom) 137 | ``` 138 | 139 | Run PCA on the BANKSY matrix: 140 | 141 | ```{r pca, eval=T, message=FALSE, warning=FALSE} 142 | lambda <- 0.2 143 | npcs <- 20 144 | use_agf <- TRUE 145 | spe <- runBanksyPCA(spe, use_agf = use_agf, lambda = lambda, npcs = npcs, seed = SEED) 146 | ``` 147 | 148 | # Run Harmony on BANKSY's embedding 149 | 150 | We run Harmony on the PCs of the BANKSY matrix: 151 | 152 | ```{r harmony, eval=T, message=FALSE, warning=FALSE} 153 | set.seed(SEED) 154 | harmony_embedding <- HarmonyMatrix( 155 | data_mat = reducedDim(spe, "PCA_M1_lam0.2"), 156 | meta_data = colData(spe), 157 | vars_use = c("sample_id", "subject_id"), 158 | do_pca = FALSE, 159 | max.iter.harmony = 20, 160 | verbose = FALSE 161 | ) 162 | reducedDim(spe, "Harmony_BANKSY") <- harmony_embedding 163 | ``` 164 | 165 | Next, run UMAP on the 'raw' and Harmony corrected PCA embeddings: 166 | 167 | ```{r umap, eval=T, message=FALSE, warning=FALSE} 168 | spe <- runBanksyUMAP(spe, use_agf = TRUE, lambda = lambda, npcs = npcs) 169 | spe <- runBanksyUMAP(spe, dimred = "Harmony_BANKSY") 170 | ``` 171 | 172 | Visualize the UMAPs annotated by subject ID: 173 | 174 | ```{r batch-correction-umap, eval=T, fig.height=3.5, out.width='90%', message=FALSE, warning=FALSE} 175 | plot_grid( 176 | plotReducedDim(spe, "UMAP_M1_lam0.2", 177 | point_size = 0.1, 178 | point_alpha = 0.5, 179 | color_by = "subject_id") + 180 | theme(legend.position = "none"), 181 | plotReducedDim(spe, "UMAP_Harmony_BANKSY", 182 | point_size = 0.1, 183 | point_alpha = 0.5, 184 | color_by = "subject_id") + 185 | theme(legend.title = element_blank()) + 186 | guides(colour = guide_legend(override.aes = list(size = 5, alpha = 1))), 187 | nrow = 1, 188 | rel_widths = c(1, 1.2) 189 | ) 190 | ``` 191 | 192 | Cluster the Harmony corrected PCA embedding: 193 | 194 | ```{r, eval=T, message=FALSE, warning=FALSE} 195 | spe <- clusterBanksy(spe, dimred = "Harmony_BANKSY", resolution = 0.55, seed = SEED) 196 | spe <- connectClusters(spe, map_to = "clust_annotation") 197 | ``` 198 | 199 | Generate spatial plots: 200 | 201 | ```{r batch-correction-spatial, eval=T, fig.height=4, out.width='90%', message=FALSE, warning=FALSE} 202 | cnm <- clusterNames(spe)[2] 203 | spatial_plots <- lapply(sample_names, function(snm) { 204 | x <- spe[, spe$sample_id == snm] 205 | ari <- aricode::ARI(x$clust_annotation, colData(x)[, cnm]) 206 | 207 | df <- cbind.data.frame(clust=colData(x)[[cnm]], spatialCoords(x)) 208 | ggplot(df, aes(x=sdimy, y=sdimx, col=clust)) + 209 | geom_point(size = 0.5) + 210 | scale_color_manual(values = pals::kelly()[-1]) + 211 | theme_classic() + 212 | theme( 213 | legend.position = "none", 214 | axis.text.x=element_blank(), 215 | axis.text.y=element_blank(), 216 | axis.ticks=element_blank(), 217 | axis.title.x=element_blank(), 218 | axis.title.y=element_blank()) + 219 | labs(title = sprintf("Sample %s - ARI: %s", snm, round(ari, 3))) + 220 | coord_equal() 221 | }) 222 | 223 | plot_grid(plotlist = spatial_plots, ncol = 3, byrow = FALSE) 224 | ``` 225 | 226 | # Session information 227 | 228 | Vignette runtime: 229 | 230 | ```{r, eval=TRUE, echo=FALSE} 231 | Sys.time() - start.time 232 | ``` 233 | 234 |
    235 | 236 | ```{r, sess} 237 | sessionInfo() 238 | ``` 239 | 240 |
    241 | -------------------------------------------------------------------------------- /vignettes/domain-segment.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Domain segmentation (STARmap PLUS mouse brain)" 3 | output: BiocStyle::html_document 4 | # output: pdf_document 5 | vignette: > 6 | %\VignetteIndexEntry{Domain segmentation (STARmap PLUS mouse brain)} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | %\VignetteEncoding{UTF-8} 9 | --- 10 | 11 | ```{r, include = FALSE} 12 | knitr::opts_chunk$set( 13 | collapse = TRUE, 14 | comment = "#>", 15 | fig.path = 'figures/' 16 | ) 17 | ``` 18 | 19 | Here, we demonstrate BANKSY domain segmentation on a STARmap PLUS dataset of 20 | the mouse brain from [Shi et al. (2022)](https://doi.org/10.1101/2022.06.20.496914). 21 | 22 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 23 | library(Banksy) 24 | 25 | library(data.table) 26 | library(SummarizedExperiment) 27 | library(SpatialExperiment) 28 | 29 | library(scater) 30 | library(cowplot) 31 | library(ggplot2) 32 | ``` 33 | 34 | ```{r, eval=TRUE, echo=FALSE} 35 | se <- readRDS(system.file("extdata/STARmap.rds", package = "Banksy")) 36 | ``` 37 | 38 | # Data preprocessing 39 | 40 | Data from the study is available from the [Single Cell Portal](https://singlecell.broadinstitute.org/single_cell/study/SCP1830). We 41 | analyze data from `well11`. The data comprise 1,022 genes profiled at 42 | subcellular resolution in 43,341 cells. 43 | 44 | ```{r, eval=FALSE} 45 | #' Change paths accordingly 46 | gcm_path <- "../data/well11processed_expression_pd.csv.gz" 47 | mdata_path <- "../data/well11_spatial.csv.gz" 48 | 49 | #' Gene cell matrix 50 | gcm <- fread(gcm_path) 51 | genes <- gcm$GENE 52 | gcm <- as.matrix(gcm[, -1]) 53 | rownames(gcm) <- genes 54 | 55 | #' Spatial coordinates and metadata 56 | mdata <- fread(mdata_path, skip = 1) 57 | headers <- names(fread(mdata_path, nrows = 0)) 58 | colnames(mdata) <- headers 59 | #' Orient spatial coordinates 60 | xx <- mdata$X 61 | yy <- mdata$Y 62 | mdata$X <- max(yy) - yy 63 | mdata$Y <- max(xx) - xx 64 | mdata <- data.frame(mdata) 65 | rownames(mdata) <- colnames(gcm) 66 | 67 | locs <- as.matrix(mdata[, c("X", "Y", "Z")]) 68 | 69 | #' Create SpatialExperiment 70 | se <- SpatialExperiment( 71 | assay = list(processedExp = gcm), 72 | spatialCoords = locs, 73 | colData = mdata 74 | ) 75 | ``` 76 | 77 | # Running BANKSY 78 | 79 | Run BANKSY in domain segmentation mode with `lambda=0.8`. This places larger 80 | weights on the mean neighborhood expression and azimuthal Gabor filter in 81 | constructing the BANKSY matrix. We adjust the resolution to yield 23 clusters 82 | based on the results from [Maher et al. (2023)](https://doi.org/10.1101/2023.06.30.547258v1) 83 | (see Fig. 1, 2). 84 | 85 | > Note that the parameter values for domain segmentation for datasets generated using the older [Visium v1 / v2 55um technologies](https://doi.org/10.1038/s41593-020-00787-0) are `lambda = 0.2` and `k_geom = 18`. See the note in the tutorial on the main [page](https://github.com/prabhakarlab/Banksy) for more details. 86 | 87 | ```{r, eval=FALSE} 88 | lambda <- 0.8 89 | k_geom <- 30 90 | npcs <- 50 91 | aname <- "processedExp" 92 | se <- Banksy::computeBanksy(se, assay_name = aname, k_geom = k_geom) 93 | 94 | set.seed(1000) 95 | se <- Banksy::runBanksyPCA(se, lambda = lambda, npcs = npcs) 96 | 97 | set.seed(1000) 98 | se <- Banksy::clusterBanksy(se, lambda = lambda, npcs = npcs, resolution = 0.8) 99 | ``` 100 | 101 | Cluster labels are stored in the `colData` slot: 102 | 103 | ```{r, eval=TRUE} 104 | head(colData(se)) 105 | ``` 106 | 107 | Visualize clustering results: 108 | 109 | ```{r domain-segment-spatial, eval=FALSE, fig.height=8, fig.width=7, fig.align='center'} 110 | cnames <- colnames(colData(se)) 111 | cnames <- cnames[grep("^clust", cnames)] 112 | 113 | plotColData(se, x = "X", y = "Y", point_size = 0.01, colour_by = cnames[1]) + 114 | scale_color_manual(values = pals::glasbey()) + 115 | coord_equal() + 116 | theme(legend.position = "none") 117 | ``` 118 | 119 |
    120 | ![](figures/domain-segment-spatial-1.png) 121 |
    122 | 123 | # Session information 124 | 125 |
    126 | 127 | ```{r, sess} 128 | sessionInfo() 129 | ``` 130 | 131 |
    132 | -------------------------------------------------------------------------------- /vignettes/figures/batch-correction-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/vignettes/figures/batch-correction-spatial-1.png -------------------------------------------------------------------------------- /vignettes/figures/batch-correction-umap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/vignettes/figures/batch-correction-umap-1.png -------------------------------------------------------------------------------- /vignettes/figures/domain-segment-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/vignettes/figures/domain-segment-spatial-1.png -------------------------------------------------------------------------------- /vignettes/figures/multi-sample-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/vignettes/figures/multi-sample-spatial-1.png -------------------------------------------------------------------------------- /vignettes/figures/multi-sample-umap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/vignettes/figures/multi-sample-umap-1.png -------------------------------------------------------------------------------- /vignettes/figures/parameter-selection-spatial-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/prabhakarlab/Banksy/08d2d91fbdf8d13c2346f8daf90a2f6b57597b36/vignettes/figures/parameter-selection-spatial-1.png -------------------------------------------------------------------------------- /vignettes/multi-sample.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Multi-sample analysis (10x Visium Human DLPFC)" 3 | output: BiocStyle::html_document 4 | # output: pdf_document 5 | vignette: > 6 | %\VignetteIndexEntry{Multi-sample analysis (10x Visium Human DLPFC)} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | %\VignetteEncoding{UTF-8} 9 | --- 10 | 11 | ```{r, include = FALSE} 12 | knitr::opts_chunk$set( 13 | collapse = TRUE, 14 | comment = "#>", 15 | fig.path = "figures/", 16 | dpi = 36 17 | ) 18 | ``` 19 | 20 | Here, we demonstrate BANKSY analysis on 10x Visium data of the human 21 | dorsolateral prefrontal cortex from Maynard et al (2018). The data comprise 12 22 | samples obtained from 3 subjects, with manual annotation of the layers in each 23 | sample. We will focus on 4 of the 12 samples from subject 3, demonstrating 24 | multi-sample analysis with BANKSY. 25 | 26 | ```{r, eval=TRUE, include=FALSE} 27 | start.time <- Sys.time() 28 | ``` 29 | 30 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 31 | library(Banksy) 32 | library(SummarizedExperiment) 33 | library(SpatialExperiment) 34 | library(Seurat) 35 | 36 | library(scater) 37 | library(cowplot) 38 | library(ggplot2) 39 | ``` 40 | 41 | # Loading the data 42 | 43 | We fetch the data for all 12 DLPFC samples with the [*spatialLIBD*](https://bioconductor.org/packages/release/data/experiment/html/spatialLIBD.html) 44 | package. This might take awhile. 45 | 46 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 47 | library(spatialLIBD) 48 | library(ExperimentHub) 49 | 50 | ehub <- ExperimentHub::ExperimentHub() 51 | spe <- spatialLIBD::fetch_data(type = "spe", eh = ehub) 52 | 53 | ``` 54 | 55 | After the download is completed, we trim the *SpatialExperiment* object, 56 | retaining only the counts and some metadata such as the sample identifier and 57 | pathology annotations. This saves some memory. 58 | 59 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 60 | imgData(spe) <- NULL 61 | assay(spe, "logcounts") <- NULL 62 | reducedDims(spe) <- NULL 63 | rowData(spe) <- NULL 64 | colData(spe) <- DataFrame( 65 | sample_id = spe$sample_id, 66 | clust_annotation = factor( 67 | addNA(spe$layer_guess_reordered_short), 68 | exclude = NULL, labels = seq(8) 69 | ), 70 | in_tissue = spe$in_tissue, 71 | row.names = colnames(spe) 72 | ) 73 | invisible(gc()) 74 | ``` 75 | 76 | Next, subset `spe` to samples from the last subject (samples `151673`, 77 | `151674`, `151675`, `151676`). This stores each sample in its own 78 | *SpatialExperiment* object, all placed in a list. 79 | 80 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 81 | sample_names <- as.character(151673:151676) 82 | spe_list <- lapply(sample_names, function(x) spe[, spe$sample_id == x]) 83 | rm(spe) 84 | invisible(gc()) 85 | ``` 86 | 87 | # Data preprocessing 88 | 89 | Using Seurat, we perform basic normalisation of the data, and select the top 90 | 2000 highly variable features from each sample. Other methods for normalisation 91 | and feature selection may also be used. We take the union of these features for 92 | downstream analysis. 93 | 94 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 95 | #' Normalize data 96 | seu_list <- lapply(spe_list, function(x) { 97 | x <- as.Seurat(x, data = NULL) 98 | NormalizeData(x, scale.factor = 5000, normalization.method = 'RC') 99 | }) 100 | 101 | #' Compute HVGs 102 | hvgs <- lapply(seu_list, function(x) { 103 | VariableFeatures(FindVariableFeatures(x, nfeatures = 2000)) 104 | }) 105 | hvgs <- Reduce(union, hvgs) 106 | 107 | #' Add data to SpatialExperiment and subset to HVGs 108 | aname <- "normcounts" 109 | spe_list <- Map(function(spe, seu) { 110 | assay(spe, aname) <- GetAssayData(seu) 111 | spe[hvgs,] 112 | }, spe_list, seu_list) 113 | rm(seu_list) 114 | invisible(gc()) 115 | ``` 116 | 117 | # Running BANKSY 118 | 119 | To run BANKSY across multiple samples, we first compute the BANKSY neighborhood 120 | feature matrices for each sample separately. We use `k_geom=6` corresponding to 121 | the first-order neighbors in 10x Visium assays (`k_geom=18` corresponding to 122 | first and second-order neighbors may also be used). 123 | 124 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 125 | compute_agf <- FALSE 126 | k_geom <- 6 127 | spe_list <- lapply(spe_list, computeBanksy, assay_name = aname, 128 | compute_agf = compute_agf, k_geom = k_geom) 129 | ``` 130 | 131 | We then merge the samples to perform joint dimensional reduction and 132 | clustering: 133 | 134 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 135 | spe_joint <- do.call(cbind, spe_list) 136 | rm(spe_list) 137 | invisible(gc()) 138 | ``` 139 | 140 | When running multi-sample BANKSY PCA, the `group` argument may be provided. 141 | This specifies the grouping variable for the cells or spots across the samples. 142 | Features belonging to cells or spots corresponding to each level of the 143 | grouping variable will be z-scaled separately. In this case, `sample_id` in 144 | `colData(spe_joint)` gives the grouping based on the sample of origin. 145 | 146 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 147 | lambda <- 0.2 148 | use_agf <- FALSE 149 | spe_joint <- runBanksyPCA(spe_joint, use_agf = use_agf, lambda = lambda, group = "sample_id", seed = 1000) 150 | ``` 151 | 152 | Run UMAP on the BANKSY embedding: 153 | 154 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 155 | spe_joint <- runBanksyUMAP(spe_joint, use_agf = use_agf, lambda = lambda, seed = 1000) 156 | ``` 157 | 158 | Finally, we obtain cluster labels for spots across all 4 samples. We use 159 | `connectClusters` for visual comparison of the manual annotations and BANKSY 160 | clusters. 161 | 162 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 163 | res <- 0.7 164 | spe_joint <- clusterBanksy(spe_joint, use_agf = use_agf, lambda = lambda, resolution = res, seed = 1000) 165 | cnm <- sprintf("clust_M%s_lam%s_k50_res%s", as.numeric(use_agf), lambda, res) 166 | spe_joint <- connectClusters(spe_joint) 167 | ``` 168 | 169 | Once joint clustering is performed, we split the samples into their own 170 | `SpatialExperiment` objects: 171 | 172 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 173 | spe_list <- lapply(sample_names, function(x) spe_joint[, spe_joint$sample_id == x]) 174 | rm(spe_joint) 175 | invisible(gc()) 176 | ``` 177 | 178 | As an optional step, we smooth the cluster labels of each sample separately. 179 | This can be done if smooth spatial domains are expected in the biological 180 | sample or tissue in question. 181 | 182 | ```{r, eval=TRUE, message=FALSE, warning=FALSE} 183 | spe_list <- lapply(spe_list, smoothLabels, cluster_names = cnm, k = 6L, verbose = FALSE) 184 | names(spe_list) <- paste0("sample_", sample_names) 185 | ``` 186 | 187 | The raw and smoothed cluster labels are stored in the `colData` slot of each 188 | `SingleCellExperiment` or `SpatialExperiment` object. 189 | 190 | ```{r, eval=TRUE, echo=FALSE} 191 | head(colData(spe_list$sample_151673)) 192 | ``` 193 | 194 | # Parsing BANKSY output 195 | 196 | We can compare BANKSY clusters to pathology annotations using several cluster 197 | comparison measures such as the adjusted Rand index (ARI) or normalized mutual 198 | information (NMI) with `compareClusters`. The function computes the selected 199 | comparison measure between all pairs of cluster labels: 200 | 201 | ```{r, eval=TRUE} 202 | compareClusters(spe_list$sample_151673, func = 'ARI') 203 | ``` 204 | 205 | We evaluate the ARI and NMI for each sample: 206 | 207 | ```{r, eval=TRUE} 208 | ari <- sapply(spe_list, function(x) as.numeric(tail(compareClusters(x, func = "ARI")[, 1], n = 1))) 209 | ari 210 | ``` 211 | 212 | ```{r, eval=TRUE} 213 | nmi <- sapply(spe_list, function(x) as.numeric(tail(compareClusters(x, func = "NMI")[, 1], n = 1))) 214 | nmi 215 | ``` 216 | 217 | Visualise pathology annotation and BANKSY cluster on spatial coordinates with 218 | the [*ggspavis*](https://bioconductor.org/packages/ggspavis) package: 219 | 220 | ```{r multi-sample-spatial, eval=TRUE, fig.height=4, out.width='90%'} 221 | # Use scater:::.get_palette('tableau10medium') 222 | pal <- c( 223 | "#729ECE", "#FF9E4A", "#67BF5C", "#ED665D", "#AD8BC9", 224 | "#A8786E", "#ED97CA", "#A2A2A2", "#CDCC5D", "#6DCCDA" 225 | ) 226 | 227 | plot_bank <- lapply(spe_list, function(x) { 228 | df <- cbind.data.frame( 229 | clust=colData(x)[[sprintf("%s_smooth", cnm)]], spatialCoords(x)) 230 | ggplot(df, aes(x=pxl_row_in_fullres, y=pxl_col_in_fullres, col=clust)) + 231 | geom_point(size = 0.5) + 232 | scale_color_manual(values = pal) + 233 | theme_classic() + 234 | theme( 235 | legend.position = "none", 236 | axis.text.x=element_blank(), 237 | axis.text.y=element_blank(), 238 | axis.ticks=element_blank(), 239 | axis.title.x=element_blank(), 240 | axis.title.y=element_blank()) + 241 | labs(title = "BANKSY clusters") + 242 | coord_equal() 243 | }) 244 | 245 | plot_anno <- lapply(spe_list, function(x) { 246 | df <- cbind.data.frame( 247 | clust=colData(x)[['clust_annotation']], spatialCoords(x)) 248 | ggplot(df, aes(x=pxl_row_in_fullres, y=pxl_col_in_fullres, col=clust)) + 249 | geom_point(size = 0.5) + 250 | scale_color_manual(values = pal) + 251 | theme_classic() + 252 | theme( 253 | legend.position = "none", 254 | axis.text.x=element_blank(), 255 | axis.text.y=element_blank(), 256 | axis.ticks=element_blank(), 257 | axis.title.x=element_blank(), 258 | axis.title.y=element_blank()) + 259 | labs(title = sprintf("Sample %s", x$sample_id[1])) + 260 | coord_equal() 261 | }) 262 | 263 | plot_list <- c(plot_anno, plot_bank) 264 | 265 | plot_grid(plotlist = plot_list, ncol = 4, byrow = TRUE) 266 | ``` 267 | 268 | Visualize joint UMAPs for each sample: 269 | 270 | ```{r multi-sample-umap, eval=TRUE, fig.height=5, out.width='90%'} 271 | umap_bank <- lapply(spe_list, function(x) { 272 | plotReducedDim(x, 273 | "UMAP_M0_lam0.2", 274 | colour_by = sprintf("%s_smooth", cnm), 275 | point_size = 0.5 276 | ) + 277 | theme(legend.position = "none") + 278 | labs(title = "BANKSY clusters") 279 | }) 280 | 281 | umap_anno <- lapply(spe_list, function(x) { 282 | plotReducedDim(x, 283 | "UMAP_M0_lam0.2", 284 | colour_by = "clust_annotation", 285 | point_size = 0.5 286 | ) + 287 | theme(legend.position = "none") + 288 | labs(title = sprintf("Sample %s", x$sample_id[1])) 289 | }) 290 | 291 | umap_list <- c(umap_anno, umap_bank) 292 | 293 | plot_grid(plotlist = umap_list, ncol = 4, byrow = TRUE) 294 | ``` 295 | 296 | # Session information 297 | 298 | Vignette runtime: 299 | 300 | ```{r, eval=TRUE, echo=FALSE} 301 | Sys.time() - start.time 302 | ``` 303 | 304 |
    305 | 306 | ```{r, sess} 307 | sessionInfo() 308 | ``` 309 | 310 |
    311 | -------------------------------------------------------------------------------- /vignettes/parameter-selection.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Parameter selection (VeraFISH Mouse Hippocampus)" 3 | output: BiocStyle::html_document 4 | # output: pdf_document 5 | vignette: > 6 | %\VignetteIndexEntry{Parameter selection (VeraFISH Mouse Hippocampus)} 7 | %\VignetteEngine{knitr::rmarkdown} 8 | %\VignetteEncoding{UTF-8} 9 | --- 10 | 11 | ```{r, include = FALSE} 12 | knitr::opts_chunk$set( 13 | collapse = TRUE, 14 | comment = "#>", 15 | fig.path = "figures/", 16 | dpi = 36 17 | ) 18 | ``` 19 | 20 | Here, we demonstrate a grid search of clustering parameters with a mouse 21 | hippocampus VeraFISH dataset. *BANKSY* currently provides four algorithms for 22 | clustering the BANKSY matrix with *clusterBanksy*: Leiden (default), Louvain, 23 | k-means, and model-based clustering. In this vignette, we run only Leiden 24 | clustering. See `?clusterBanksy` for more details on the parameters for 25 | different clustering methods. 26 | 27 | # Loading the data 28 | 29 | ```{r, eval=TRUE, include=F} 30 | start.time <- Sys.time() 31 | ``` 32 | 33 | The dataset comprises gene expression for 10,944 cells and 120 genes in 2 34 | spatial dimensions. See `?Banksy::hippocampus` for more details. 35 | 36 | ```{r, eval=TRUE, warning=FALSE, message=FALSE} 37 | # Load libs 38 | library(Banksy) 39 | 40 | library(SummarizedExperiment) 41 | library(SpatialExperiment) 42 | library(scuttle) 43 | 44 | library(scater) 45 | library(cowplot) 46 | library(ggplot2) 47 | 48 | # Load data 49 | data(hippocampus) 50 | gcm <- hippocampus$expression 51 | locs <- as.matrix(hippocampus$locations) 52 | ``` 53 | 54 | Here, `gcm` is a gene by cell matrix, and `locs` is a matrix specifying the 55 | coordinates of the centroid for each cell. 56 | 57 | ```{r, eval=TRUE} 58 | head(gcm[,1:5]) 59 | head(locs) 60 | ``` 61 | 62 | Initialize a SpatialExperiment object and perform basic quality control. We 63 | keep cells with total transcript count within the 5th and 98th percentile: 64 | 65 | ```{r, eval=TRUE, message=FALSE} 66 | se <- SpatialExperiment(assay = list(counts = gcm), spatialCoords = locs) 67 | colData(se) <- cbind(colData(se), spatialCoords(se)) 68 | 69 | # QC based on total counts 70 | qcstats <- perCellQCMetrics(se) 71 | thres <- quantile(qcstats$total, c(0.05, 0.98)) 72 | keep <- (qcstats$total > thres[1]) & (qcstats$total < thres[2]) 73 | se <- se[, keep] 74 | ``` 75 | 76 | Next, perform normalization of the data. 77 | 78 | ```{r, eval=TRUE, message=FALSE} 79 | # Normalization to mean library size 80 | se <- computeLibraryFactors(se) 81 | aname <- "normcounts" 82 | assay(se, aname) <- normalizeCounts(se, log = FALSE) 83 | ``` 84 | 85 | # Parameters 86 | 87 | *BANKSY* has a few key parameters. We describe these below. 88 | 89 | ## AGF usage 90 | 91 | For characterising neighborhoods, *BANKSY* computes the weighted neighborhood 92 | mean (`H_0`) and the azimuthal Gabor filter (`H_1`), which estimates gene 93 | expression gradients. Setting `compute_agf=TRUE` computes both `H_0` and `H_1`. 94 | 95 | ## k-geometric 96 | 97 | `k_geom` specifies the number of neighbors used to compute each `H_m` for 98 | `m=0,1`. If a single value is specified, the same `k_geom` will be used 99 | for each feature matrix. Alternatively, multiple values of `k_geom` can be 100 | provided for each feature matrix. Here, we use `k_geom[1]=15` and 101 | `k_geom[2]=30` for `H_0` and `H_1` respectively. More neighbors are used to 102 | compute gradients. 103 | 104 | > For datasets generated using Visium v1/v2, use `k_geom=18` (or `k_geom <- c(18, 18)` if `compute_agf = TRUE`), since that corresponds to taking as neighbourhood two concentric rings of spots around each spot. 105 | 106 | We compute the neighborhood feature matrices using normalized expression 107 | (`normcounts` in the `se` object). 108 | 109 | ```{r, eval=TRUE} 110 | k_geom <- c(15, 30) 111 | se <- computeBanksy(se, assay_name = aname, compute_agf = TRUE, k_geom = k_geom) 112 | ``` 113 | 114 | `computeBanksy` populates the `assays` slot with `H_0` and `H_1` in this 115 | instance: 116 | 117 | ```{r, eval=TRUE} 118 | se 119 | ``` 120 | 121 | ## lambda 122 | 123 | The `lambda` parameter is a mixing parameter in `[0,1]` which 124 | determines how much spatial information is incorporated for downstream analysis. 125 | With smaller values of `lambda`, BANKY operates in *cell-typing* mode, while at 126 | higher levels of `lambda`, BANKSY operates in *domain-finding* mode. As a 127 | starting point, we recommend `lambda=0.2` for cell-typing and `lambda=0.8` for 128 | zone-finding, **except for datasets generated using the Visium v1/v2 technology**, for which 129 | we [recommend](https://prabhakarlab.github.io/Banksy/articles/multi-sample.html) 130 | `lambda=0.2` for domain finding. See the note in the tutorial on the 131 | [main page](https://github.com/prabhakarlab/Banksy) for more info. 132 | 133 | Here, we run `lambda=0` which corresponds to non-spatial 134 | clustering, and `lambda=0.2` for spatially-informed cell-typing. We compute PCs 135 | with and without the AGF (`H_1`). 136 | 137 | ```{r, eval=TRUE} 138 | lambda <- c(0, 0.2) 139 | se <- runBanksyPCA(se, use_agf = c(FALSE, TRUE), lambda = lambda, seed = 1000) 140 | ``` 141 | 142 | `runBanksyPCA` populates the `reducedDims` slot, with each combination of 143 | `use_agf` and `lambda` provided. 144 | 145 | ```{r, eval=TRUE} 146 | reducedDimNames(se) 147 | ``` 148 | 149 | ## Clustering parameters 150 | 151 | Next, we cluster the BANKSY embedding with Leiden graph-based clustering. This 152 | admits two parameters: `k_neighbors` and `resolution`. `k_neighbors` determines 153 | the number of k nearest neighbors used to construct the shared nearest 154 | neighbors graph. Leiden clustering is then performed on the resultant graph 155 | with resolution `resolution`. For reproducibiltiy we set a seed for each 156 | parameter combination. 157 | 158 | ```{r, eval=TRUE} 159 | k <- 50 160 | res <- 1 161 | se <- clusterBanksy(se, use_agf = c(FALSE, TRUE), lambda = lambda, k_neighbors = k, resolution = res, seed = 1000) 162 | ``` 163 | 164 | `clusterBanksy` populates `colData(se)` with cluster labels: 165 | ```{r, eval=TRUE} 166 | colnames(colData(se)) 167 | ``` 168 | 169 | # Comparing cluster results 170 | 171 | To compare clustering runs visually, different runs can be relabeled to 172 | minimise their differences with `connectClusters`: 173 | 174 | ```{r, eval=TRUE} 175 | se <- connectClusters(se) 176 | ``` 177 | 178 | Visualise spatial coordinates with cluster labels. 179 | 180 | ```{r parameter-selection-spatial, eval=TRUE, fig.height=7, out.width='90%'} 181 | cnames <- colnames(colData(se)) 182 | cnames <- cnames[grep("^clust", cnames)] 183 | cplots <- lapply(cnames, function(cnm) { 184 | plotColData(se, x = "sdimx", y = "sdimy", point_size = 0.1, colour_by = cnm) + 185 | coord_equal() + 186 | labs(title = cnm) + 187 | theme(legend.title = element_blank()) + 188 | guides(colour = guide_legend(override.aes = list(size = 2))) 189 | }) 190 | 191 | plot_grid(plotlist = cplots, ncol = 2) 192 | ``` 193 | 194 | Compare all cluster outputs with `compareClusters`. This function computes 195 | pairwise cluster comparison metrics between the clusters in `colData(se)` based 196 | on adjusted Rand index (ARI): 197 | 198 | ```{r, eval=TRUE} 199 | compareClusters(se, func = "ARI") 200 | ``` 201 | 202 | or normalized mutual information (NMI): 203 | 204 | ```{r, eval=TRUE} 205 | compareClusters(se, func = "NMI") 206 | ``` 207 | 208 | See `?compareClusters` for the full list of comparison measures. 209 | 210 | # Session information 211 | 212 | Vignette runtime: 213 | 214 | ```{r, eval=TRUE, echo=FALSE} 215 | Sys.time() - start.time 216 | ``` 217 | 218 |
    219 | 220 | ```{r, sess} 221 | sessionInfo() 222 | ``` 223 | 224 |
    225 | --------------------------------------------------------------------------------