By default,
runBanksyPCA uses a lazy linear operator that computes PCA
without materializing the full BANKSY matrix. This is memory-efficient
and recommended for most use cases.
However, some workflows require explicit construction of the BANKSY
matrix — for example, when using the azimuthal Gabor filter (AGF), when
access to the intermediate matrices is needed, or when using higher
harmonics (M > 0). This vignette demonstrates the
standard workflow using computeBanksy followed by
runBanksyPCA(lazy=FALSE).
library(Banksy)
library(SummarizedExperiment)
library(SpatialExperiment)
library(scuttle)
library(scater)
library(cowplot)
library(ggplot2)We use the mouse hippocampus dataset provided with Banksy.
Initialize a SpatialExperiment object and perform quality control and normalization.
se <- SpatialExperiment(assay = list(counts = gcm), spatialCoords = locs)
# QC based on total counts
qcstats <- perCellQCMetrics(se)
#> Warning in .per_cell_qc_metrics(assay(x, assay.type), subsets = subsets, : 'perCellQCMetrics' is deprecated.
#> Use 'scrapper::computeRnaQcMetrics' instead.
#> See help("Deprecated")
thres <- quantile(qcstats$total, c(0.05, 0.98))
keep <- (qcstats$total > thres[1]) & (qcstats$total < thres[2])
se <- se[, keep]
# Normalization to mean library size
se <- computeLibraryFactors(se)
#> Warning in .library_size_factors(assay(x, assay.type), ...): 'librarySizeFactors' is deprecated.
#> Use 'scrapper::centerSizeFactors' instead.
#> See help("Deprecated")
aname <- "normcounts"
assay(se, aname) <- normalizeCounts(se, log = FALSE)
#> Warning in .local(x, ...): 'normalizeCounts' is deprecated.
#> Use 'scrapper::normalizeCounts' instead.
#> See help("Deprecated")computeBanksy computes the neighborhood matrices and
stores them as assays in the SpatialExperiment object. Setting
compute_agf=TRUE computes both the weighted neighborhood
mean (\(\mathcal{M}\)) and the
azimuthal Gabor filter (\(\mathcal{G}\)). The number of spatial
neighbors used to compute \(\mathcal{M}\) and \(\mathcal{G}\) are k_geom[1]=15
and k_geom[2]=30 respectively.
k_geom <- c(15, 30)
se <- computeBanksy(se, assay_name = aname, compute_agf = TRUE, k_geom = k_geom)
#> Computing neighbors...
#> Spatial mode is kNN_median
#> Parameters: k_geom=15
#> Done
#> Computing neighbors...
#> Spatial mode is kNN_median
#> Parameters: k_geom=30
#> Done
#> Computing harmonic m = 0 with 15 neighbors
#> Done
#> Computing harmonic m = 1 with 30 neighbors
#> Centering
#> DoneAfter running computeBanksy, the neighborhood matrices
are accessible as assays:
We run PCA with lazy=FALSE to use the standard path,
which constructs the full BANKSY matrix via
getBanksyMatrix. Setting use_agf=TRUE uses
both \(\mathcal{M}\) and \(\mathcal{G}\). We compare non-spatial
clustering (lambda=0) with BANKSY cell-typing
(lambda=0.2).
lambda <- c(0, 0.2)
set.seed(1000)
se <- runBanksyPCA(se, use_agf = TRUE, lambda = lambda, lazy = FALSE)
se <- runBanksyUMAP(se, use_agf = TRUE, lambda = lambda)
se <- clusterBanksy(se, use_agf = TRUE, lambda = lambda, resolution = 1.2)
se <- connectClusters(se)
#> clust_M1_lam0.2_k50_res1.2 --> clust_M1_lam0_k50_res1.2Visualise the clustering output:
cnames <- colnames(colData(se))
cnames <- cnames[grep("^clust", cnames)]
colData(se) <- cbind(colData(se), spatialCoords(se))
plot_nsp <- plotColData(se,
x = "sdimx", y = "sdimy",
point_size = 0.6, colour_by = cnames[1]
)
plot_bank <- plotColData(se,
x = "sdimx", y = "sdimy",
point_size = 0.6, colour_by = cnames[2]
)
plot_grid(plot_nsp + coord_equal(), plot_bank + coord_equal(), ncol = 2)The full BANKSY matrix can be retrieved with
getBanksyMatrix. This is useful for custom downstream
analyses.
banksy_matrix <- getBanksyMatrix(se, M = 1, lambda = 0.2,
assay_name = aname, scale = TRUE)
dim(banksy_matrix)
#> [1] 360 10205options(width = 120)
sessioninfo::session_info()
#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.6.1 (2026-06-24)
#> os Ubuntu 26.04.1 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language (EN)
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz Etc/UTC
#> date 2026-09-30
#> pandoc 3.8.3 @ /usr/local/bin/ (via rmarkdown)
#> quarto 1.9.37 @ /usr/local/bin/quarto
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> abind 1.4-8 2024-09-12 [2] RSPM (R 4.6.0)
#> aricode 1.1.0 2026-05-13 [2] RSPM (R 4.6.0)
#> Banksy * 1.9.4 2026-09-29 [1] https://bioc.r-universe.dev (R 4.6.1)
#> beachmat 2.29.3 2026-09-23 [2] https://bioc.r-universe.dev (R 4.6.1)
#> beeswarm 0.4.0 2021-06-01 [2] RSPM (R 4.6.0)
#> Biobase * 2.73.2 2026-07-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocGenerics * 0.59.12 2026-08-10 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocManager 1.30.27 2025-11-14 [2] RSPM (R 4.6.0)
#> BiocNeighbors 2.7.3 2026-08-21 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocParallel 1.47.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocSingular 1.29.1 2026-08-27 [2] https://bioc.r-universe.dev (R 4.6.1)
#> BiocStyle * 2.41.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> bslib 0.12.0 2026-08-04 [2] RSPM (R 4.6.0)
#> buildtools 1.0.0 2026-09-15 [3] local (/pkg)
#> cachem 1.1.0 2024-05-16 [2] RSPM (R 4.6.0)
#> cli 3.6.6 2026-04-09 [2] RSPM (R 4.6.0)
#> codetools 0.2-20 2024-03-31 [2] RSPM (R 4.6.0)
#> cowplot * 1.2.0 2025-07-07 [2] RSPM (R 4.6.0)
#> data.table 1.18.6.1 2026-08-24 [2] RSPM (R 4.6.0)
#> dbscan 1.2.6 2026-08-25 [2] RSPM (R 4.6.0)
#> DelayedArray 0.39.7 2026-09-23 [2] https://bioc.r-universe.dev (R 4.6.1)
#> dichromat 2.0-1 2026-07-22 [2] RSPM (R 4.6.0)
#> digest 0.6.39 2025-11-19 [2] RSPM (R 4.6.0)
#> dplyr 1.2.1 2026-04-03 [2] RSPM (R 4.6.0)
#> evaluate 1.0.5 2025-08-27 [2] RSPM (R 4.6.0)
#> farver 2.1.2 2024-05-13 [2] RSPM (R 4.6.0)
#> fastmap 1.2.0 2024-05-15 [2] RSPM (R 4.6.0)
#> generics * 0.1.4 2025-05-09 [2] RSPM (R 4.6.0)
#> GenomicRanges * 1.65.4 2026-09-02 [2] https://bioc.r-universe.dev (R 4.6.1)
#> ggbeeswarm 0.7.3 2025-11-29 [2] RSPM (R 4.6.0)
#> ggplot2 * 4.0.3 2026-04-22 [2] RSPM (R 4.6.0)
#> ggrepel 0.9.8 2026-03-17 [2] RSPM (R 4.6.0)
#> glue 1.8.1 2026-04-17 [2] RSPM (R 4.6.0)
#> gridExtra 2.3.1 2026-06-25 [2] RSPM (R 4.6.0)
#> gtable 0.3.6 2024-10-25 [2] RSPM (R 4.6.0)
#> htmltools 0.5.9 2025-12-04 [2] RSPM (R 4.6.0)
#> igraph 2.3.3 2026-06-26 [2] RSPM (R 4.6.0)
#> IRanges * 2.47.5 2026-08-27 [2] https://bioc.r-universe.dev (R 4.6.1)
#> irlba 2.3.7 2026-01-30 [2] RSPM (R 4.6.0)
#> jquerylib 0.1.4 2021-04-26 [2] RSPM (R 4.6.0)
#> jsonlite 2.0.0 2025-03-27 [2] RSPM (R 4.6.0)
#> knitr 1.52 2026-09-06 [2] RSPM (R 4.6.0)
#> labeling 0.4.3 2023-08-29 [2] RSPM (R 4.6.0)
#> lattice 0.23-1 2026-08-12 [2] RSPM (R 4.6.0)
#> leidenAlg 1.1.8 2026-05-31 [2] RSPM (R 4.6.0)
#> lifecycle 1.0.5 2026-01-08 [2] RSPM (R 4.6.0)
#> magick 2.9.1 2026-02-28 [2] RSPM (R 4.6.0)
#> magrittr 2.0.5 2026-04-04 [2] RSPM (R 4.6.0)
#> maketools 1.3.2 2025-01-25 [3] RSPM (R 4.6.0)
#> Matrix 1.7-6 2026-07-25 [2] RSPM (R 4.6.0)
#> MatrixGenerics * 1.25.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> matrixStats * 1.5.0 2025-01-07 [2] RSPM (R 4.6.0)
#> mclust 6.1.3 2026-07-05 [2] RSPM (R 4.6.0)
#> otel 0.2.0 2025-08-29 [2] RSPM (R 4.6.0)
#> pillar 1.11.1 2025-09-17 [2] RSPM (R 4.6.0)
#> pkgconfig 2.0.3 2019-09-22 [2] RSPM (R 4.6.0)
#> R6 2.6.1 2025-02-15 [2] RSPM (R 4.6.0)
#> RColorBrewer 1.1-3 2022-04-03 [2] RSPM (R 4.6.0)
#> Rcpp 1.1.2 2026-07-05 [2] RSPM (R 4.6.0)
#> RcppAnnoy 0.0.23 2026-01-12 [2] RSPM (R 4.6.0)
#> RcppHungarian 0.3 2023-09-05 [2] RSPM (R 4.6.0)
#> rjson 0.2.23 2024-09-16 [2] RSPM (R 4.6.0)
#> rlang 1.3.0 2026-07-05 [2] RSPM (R 4.6.0)
#> rmarkdown 2.32 2026-09-01 [2] RSPM (R 4.6.0)
#> RSpectra 0.16-2 2024-07-18 [2] RSPM (R 4.6.0)
#> rsvd 1.0.5 2021-04-16 [2] RSPM (R 4.6.0)
#> S4Arrays 1.13.1 2026-09-22 [2] https://bioc.r-universe.dev (R 4.6.1)
#> S4Vectors * 0.51.10 2026-09-15 [2] https://bioc.r-universe.dev (R 4.6.1)
#> S7 0.2.2 2026-04-22 [2] RSPM (R 4.6.0)
#> sass 0.4.10 2025-04-11 [2] RSPM (R 4.6.0)
#> ScaledMatrix 1.21.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> scales 1.4.0 2025-04-24 [2] RSPM (R 4.6.0)
#> scater * 1.41.2 2026-06-30 [2] https://bioc.r-universe.dev (R 4.6.1)
#> sccore 1.0.7 2026-04-06 [2] RSPM (R 4.6.0)
#> scuttle * 1.23.2 2026-08-27 [2] https://bioc.r-universe.dev (R 4.6.1)
#> Seqinfo * 1.3.2 2026-08-26 [2] https://bioc.r-universe.dev (R 4.6.1)
#> sessioninfo 1.2.4 2026-06-04 [2] RSPM (R 4.6.0)
#> SingleCellExperiment * 1.35.2 2026-07-16 [2] https://bioc.r-universe.dev (R 4.6.1)
#> SparseArray 1.13.3 2026-09-24 [2] https://bioc.r-universe.dev (R 4.6.1)
#> SpatialExperiment * 1.23.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> SummarizedExperiment * 1.43.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> sys 3.4.3 2024-10-04 [2] RSPM (R 4.6.0)
#> tibble 3.3.1 2026-01-11 [2] RSPM (R 4.6.0)
#> tidyselect 1.2.1 2024-03-11 [2] RSPM (R 4.6.0)
#> uwot 0.2.5 2026-08-29 [2] RSPM (R 4.6.0)
#> vctrs 0.7.3 2026-04-11 [2] RSPM (R 4.6.0)
#> vipor 0.4.7 2023-12-18 [2] RSPM (R 4.6.0)
#> viridis 0.6.5 2024-01-29 [2] RSPM (R 4.6.0)
#> viridisLite 0.4.3 2026-02-04 [2] RSPM (R 4.6.0)
#> withr 3.0.3 2026-06-19 [2] RSPM (R 4.6.0)
#> xfun 0.61 2026-09-16 [2] RSPM (R 4.6.0)
#> XVector 0.53.0 2026-04-28 [2] https://bioc.r-universe.dev (R 4.6.1)
#> yaml 2.3.12 2025-12-10 [2] RSPM (R 4.6.0)
#>
#> [1] /tmp/Rtmpe0t8Qn/Rinst279a59bf5c95
#> [2] /github/workspace/pkglib
#> [3] /usr/local/lib/R/site-library
#> [4] /usr/lib/R/site-library
#> [5] /usr/lib/R/library
#> * ── Packages attached to the search path.
#>
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────