Skip to contents

Introduction

This vignette walks through a typical workflow on a Visium breast cancer dataset.

Load Example Data

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

Quality control

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]

Run BLISA at the LR level

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) 
#> Downloading CellChatDB.human from GitHub (once per session)...
#> 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 level
  • LR_results — one row per LR pair, sorted by number of hotspot bins
  • bins — the hexagonal grid as an sf object
  • spatial_weights — queen and distance-decay weights from computeSpatialWeights()
  • CCI_scores — wide data frame of sender-receiver interaction scores per LR pair

Run BLISA at the pathway level

To 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.

Visualization

The plotLRrank function visualizes the top interacting pathways across the tissue, ranked by the number of significant hotspot spots.

plotLRrank(res_pathway, flip=TRUE)

Spatial Map of Hotspot Bins

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)

Session Information

sessionInfo()
#> R version 4.6.0 (2026-04-24 ucrt)
#> Platform: x86_64-w64-mingw32/x64
#> Running under: Windows 11 x64 (build 26200)
#> 
#> 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] SpatialExperiment_1.21.0    SingleCellExperiment_1.33.2 SummarizedExperiment_1.41.1 Biobase_2.71.0             
#>  [5] GenomicRanges_1.63.2        Seqinfo_1.1.0               IRanges_2.45.0              S4Vectors_0.49.2           
#>  [9] BiocGenerics_0.57.1         generics_0.1.4              MatrixGenerics_1.23.0       matrixStats_1.5.0          
#> [13] blisa_1.0.0                
#> 
#> loaded via a namespace (and not attached):
#>  [1] gtable_0.3.6          circlize_0.4.18       shape_1.4.6.1         rjson_0.2.23          xfun_0.57            
#>  [6] ggplot2_4.0.3         GlobalOptions_0.1.4   lattice_0.22-9        Cairo_1.7-0           vctrs_0.7.3          
#> [11] tools_4.6.0           spdep_1.4-2           parallel_4.6.0        tibble_3.3.1          proxy_0.4-29         
#> [16] cluster_2.1.8.2       pkgconfig_2.0.3       Matrix_1.7-5          KernSmooth_2.23-26    RColorBrewer_1.1-3   
#> [21] S7_0.2.2              lifecycle_1.0.5       deldir_2.0-4          compiler_4.6.0        farver_2.1.2         
#> [26] codetools_0.2-20      ComplexHeatmap_2.28.0 clue_0.3-68           class_7.3-23          fastLISA_1.0.1       
#> [31] pillar_1.11.1         crayon_1.5.3          classInt_0.4-11       DelayedArray_0.37.1   dbscan_1.2.4         
#> [36] wk_0.9.5              magick_2.9.1          iterators_1.0.14      boot_1.3-32           abind_1.4-8          
#> [41] foreach_1.5.2         tidyselect_1.2.1      digest_0.6.39         sf_1.1-1              dplyr_1.2.1          
#> [46] labeling_0.4.3        grid_4.6.0            colorspace_2.1-2      cli_3.6.6             SparseArray_1.11.13  
#> [51] magrittr_2.0.5        S4Arrays_1.11.1       e1071_1.7-17          withr_3.0.3           scales_1.4.0         
#> [56] sp_2.2-1              spData_2.3.5          XVector_0.51.0        otel_0.2.0            png_0.1-9            
#> [61] GetoptLong_1.1.1      evaluate_1.0.5        knitr_1.51            doParallel_1.0.17     viridisLite_0.4.3    
#> [66] s2_1.1.11             rlang_1.2.0           Rcpp_1.1.1-1.1        glue_1.8.1            DBI_1.3.0            
#> [71] R6_2.6.1              units_1.0-1