This vignette walks through a typical workflow on a Visium breast cancer dataset.
library(blisa) library(SpatialExperiment) library(ggplot2)
The example dataset is a small SpatialExperiment object (one Visium breast
cancer section) hosted as a GitHub Release asset. Download it once and cache
locally:
data_url <- "https://github.com/ChenLaboratory/example_data/releases/download/v1.0.0/spe_visium_bc_s1.rds" cache_dir <- tools::R_user_dir("blisa", "cache") data_file <- file.path(cache_dir, "spe_visium_bc_s1.rds") if (!file.exists(data_file)) { dir.create(cache_dir, recursive = TRUE, showWarnings = FALSE) download.file(data_url, data_file, mode = "wb") } spe <- readRDS(data_file) spe #> class: SpatialExperiment #> dim: 18085 4992 #> metadata(2): um_per_pixel coord_unit #> assays(1): counts #> rownames(18085): SAMD11 NOC2L ... MT-ND6 MT-CYB #> rowData names(3): ID Symbol Type #> colnames(4992): AACACCTACTATCGAA-1 AACACGTGCATCGCAC-1 ... TGTTGGCCAGACCTAC-1 TGTTGGCCTACACGTG-1 #> colData names(6): in_tissue array_row ... n_genes sample_id #> reducedDimNames(0): #> mainExpName: NULL #> altExpNames(0): #> spatialCoords names(2) : pxl_col_in_fullres pxl_row_in_fullres #> imgData names(4): sample_id image_id data scaleFactor
For a Visium data, there is no need to run hexBinCells() to bin the data.
Here we remove spots with less than 3000 total counts.
kp <- Matrix::colSums(counts(spe)) > 3000 table(kp) #> kp #> FALSE TRUE #> 580 4412 spe <- spe[,kp]
blisa() does everything in one call: spatial weights, LR pair filtering against
CellChatDB, bivariate Moran's I per LR pair, and hotspot identification.
However, as Visium data is spot-based, there is no cell type annotation by default.
Therefore, blisa() doesn't calculate cell-cell interaction scoring as for imaging-based
data such as Xenium.
res <- blisa(spe) #> Testing 462 LR pairs... #> |========================================| 100% res #> A blisa object #> Level : lr #> LR pairs tested : 462 #> Significant : 462 #> Bins : 4412 #> CCI computed : FALSE
The result is a blisa object with five slots:
Level - whether it is LR level or pathway levelLR_results — one row per LR pair, sorted by number of hotspot binsbins — the hexagonal grid as an sf objectspatial_weights — queen and distance-decay weights from computeSpatialWeights()CCI_scores — wide data frame of sender-receiver interaction scores per LR pairTo perform pathway level cell-cell communication analyses, we run blisaPathway().
res_pathway <- blisaPathway(res) res_pathway #> A blisa object #> Level : pathway #> Pathways tested : 100 #> Significant : 100 #> Bins : 4412 #> CCI computed : FALSE
By default, the pathway level result is the union of each LR pair's significant hotspot spots, with the minimum (best) p-value per spot. Two alternative methods, Simes' and Fisher's methods, are supported to combine p-values of all LR pair's across hotspot spots.
The plotLRrank function visualizes the top interacting pathways across the tissue,
ranked by the number of significant hotspot spots.
plotLRrank(res_pathway, flip=TRUE)
For a chosen pathway (here, the top-ranked pathway by default), plotHotspots shows which bins
are significant hotspots, coloured by p-value.
The H&E image can be shown in the backgound using plotImage from scider.
p_img <- scider::plotImage(spe) plotHotspots(res_pathway, index = 1, background = p_img, size = 1.2)
sessionInfo() #> R version 4.6.0 (2026-04-24 ucrt) #> Platform: x86_64-w64-mingw32/x64 #> Running under: Windows 11 x64 (build 26300) #> #> Matrix products: default #> LAPACK version 3.12.1 #> #> locale: #> [1] LC_COLLATE=English_Australia.utf8 LC_CTYPE=English_Australia.utf8 LC_MONETARY=English_Australia.utf8 #> [4] LC_NUMERIC=C LC_TIME=English_Australia.utf8 #> #> time zone: Australia/Sydney #> tzcode source: internal #> #> attached base packages: #> [1] stats4 stats graphics grDevices utils datasets methods base #> #> other attached packages: #> [1] ggplot2_4.0.3 SpatialExperiment_1.21.0 SingleCellExperiment_1.33.2 #> [4] SummarizedExperiment_1.41.1 Biobase_2.71.0 GenomicRanges_1.63.2 #> [7] Seqinfo_1.1.0 IRanges_2.45.0 S4Vectors_0.49.2 #> [10] BiocGenerics_0.57.1 generics_0.1.4 MatrixGenerics_1.23.0 #> [13] matrixStats_1.5.0 blisa_1.0.3 #> #> loaded via a namespace (and not attached): #> [1] DBI_1.3.0 deldir_2.0-4 s2_1.1.11 rlang_1.2.0 #> [5] magrittr_2.0.5 clue_0.3-68 GetoptLong_1.1.1 otel_0.2.0 #> [9] spatstat.geom_3.7-3 e1071_1.7-17 compiler_4.6.0 png_0.1-9 #> [13] vctrs_0.7.3 pkgconfig_2.0.3 wk_0.9.5 shape_1.4.6.1 #> [17] crayon_1.5.3 fastmap_1.2.0 magick_2.9.1 XVector_0.51.0 #> [21] labeling_0.4.3 promises_1.5.0 purrr_1.2.2 xfun_0.57 #> [25] jsonlite_2.0.0 goftest_1.2-3 later_1.4.8 DelayedArray_0.37.1 #> [29] spatstat.utils_3.2-2 parallel_4.6.0 cluster_2.1.8.2 R6_2.6.1 #> [33] spatstat.data_3.1-9 RColorBrewer_1.1-3 spatstat.univar_3.1-7 boot_1.3-32 #> [37] Rcpp_1.1.1-1.1 iterators_1.0.14 knitr_1.51 tensor_1.5.1 #> [41] scider_1.9.9 httpuv_1.6.17 Matrix_1.7-5 igraph_2.3.0 #> [45] tidyselect_1.2.1 abind_1.4-8 spatstat.random_3.4-5 spatstat.explore_3.8-0 #> [49] doParallel_1.0.17 codetools_0.2-20 lattice_0.22-9 tibble_3.3.1 #> [53] shiny_1.13.0 withr_3.0.3 S7_0.2.2 evaluate_1.0.5 #> [57] sf_1.1-1 polyclip_1.10-7 units_1.0-1 spData_2.3.5 #> [61] proxy_0.4-29 circlize_0.4.18 pillar_1.11.1 KernSmooth_2.23-26 #> [65] foreach_1.5.2 plotly_4.12.0 dbscan_1.2.4 sp_2.2-1 #> [69] scales_1.4.0 xtable_1.8-8 class_7.3-23 glue_1.8.1 #> [73] lazyeval_0.2.3 tools_4.6.0 data.table_1.18.2.1 grid_4.6.0 #> [77] Cairo_1.7-0 spdep_1.4-2 tidyr_1.3.2 colorspace_2.1-2 #> [81] nlme_3.1-169 fastLISA_1.0.1 fastmatrix_0.6-6 cli_3.6.6 #> [85] spatstat.sparse_3.1-0 S4Arrays_1.11.1 viridisLite_0.4.3 ComplexHeatmap_2.28.0 #> [89] dplyr_1.2.1 gtable_0.3.6 SpatialPack_0.4-1 digest_0.6.39 #> [93] classInt_0.4-11 SparseArray_1.11.13 htmlwidgets_1.6.4 rjson_0.2.23 #> [97] farver_2.1.2 htmltools_0.5.9 lifecycle_1.0.5 httr_1.4.8 #> [101] GlobalOptions_0.1.4 mime_0.13
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.