The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

Exploring cell-cell interaction with blisa

Introduction

blisa identifies spatially enriched ligand-receptor (LR) interactions from spatial transcriptomics data using bivariate Local Moran’s I (LISA) statistics. The core idea is to bin cells into a hexagonal grid, compute spatial co-enrichment of every ligand-receptor pair across bins, and flag “High-High” hotspot bins where both partners are spatially co-expressed beyond chance.

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

Load Package

library(blisa)
library(SpatialExperiment)

Load Example Data

The example dataset is a small SpatialExperiment object (one Xenium 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_xenium_bc_s1rep1.rds"
cache_dir  <- tools::R_user_dir("blisa", "cache")
data_file  <- file.path(cache_dir, "spe_xenium_bc_s1rep1.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: 313 163797 
#> metadata(0):
#> assays(1): counts
#> rownames(313): ABCC11 ACTA2 ... ZEB2 ZNF562
#> rowData names(3): ID Symbol Type
#> colnames(163797): cell_1 cell_2 ... cell_167779 cell_167780
#> colData names(12): cell_id transcript_counts ... gene_counts cell_type
#> reducedDimNames(0):
#> mainExpName: NULL
#> altExpNames(0):
#> spatialCoords names(2) : x_centroid y_centroid
#> imgData names(1): sample_id

Bin Cells into Hexagons

hexBinCells() aggregates cells into hexagonal bins. When a group argument is supplied (here, cell type), it also returns per-cell-type bin matrices in counts_by_group, which are needed downstream for CCI scoring and spatial visualisation.

coords <- as.data.frame(SpatialExperiment::spatialCoords(spe))
counts <- SummarizedExperiment::assay(spe, "counts")

binned <- hexBinCells(
  coords_df     = coords,
  counts_matrix = counts,
  bin_size      = 50,
  group         = spe$cell_type
)

# Components:
#   binned$counts_matrix   - gene x bin sparse matrix (all cells)
#   binned$bins            - sf polygons (with n_cells column)
#   binned$counts_by_group - named list of gene x bin matrices, one per cell type

Run BLISA

blisa() does everything in one call: spatial weights, LR pair filtering against CellChatDB, bivariate Moran’s I per LR pair, hotspot identification, and (when counts_by_group is supplied) cell-cell interaction scoring.

res <- blisa(
  binned$counts_matrix,
  bins            = binned$bins,
  n_cells_col     = "n_cells",
  counts_by_group = binned$counts_by_group
)
#> Downloading CellChatDB.human from GitHub (once per session)...
#> Testing 12 LR pairs...
#>   |========================================| 100%

res
#> A blisa object
#>  LR pairs tested  : 12 
#>  Significant pairs: 12 
#>  Bins             : 17215 
#>  CCI computed     : TRUE

The result is a blisa object with four slots:

Rank LR Pairs by Hotspot Count

plotLRrank(res, top = 30)

Spatial Map of Hotspot Bins

For a chosen LR pair (here, the top-ranked pair by default), shows which bins are significant hotspots, coloured by p-value or LISA score.

plotHotspots(res, index = 1)


# Or by gene names:
# plotHotspots(res, ligand = "CXCL12", receptor = "CXCR4")

Cell-Cell Interaction (CCI) Heatmaps

Across all LR pairs

Rows are sender→receiver cell-type pairs; columns are LR pairs.

plotCCI(res, top_lr = 20, top_pairs = 30)

Filter by specific senders or receivers:

plotCCI(res,
        sender = c("CD4+_T_Cells", "CD8+_T_Cells", "B_Cells",
                   "Macrophages", "DCs"),
        receiver = c("Invasive_Tumor", "DCIS", "Myoepi") )

For a single LR pair

plotCCILR(res, ligand = "CXCL12", receptor = "CXCR4")

Aggregated across LR pairs

Sender × receiver heatmap with scores summed (or any user-supplied function) across all LR pairs:

plotCCIsummary(res)


# With a different aggregation:
# plotCCIsummary(res, agg_fun = mean)

Spatial Map of Dominant Cell-Type Pairs

For each hotspot bin of a chosen LR pair, identifies the dominant sender→receiver cell-type combination based on ligand expression in the neighbourhood and receptor expression inside the bin.

plotCCIspatial(
  res,
  counts_by_group = binned$counts_by_group,
  index = 1
)

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

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.