scider is a user-friendly R package providing functions to model the global density of cells in a slide of spatial transcriptomics data. All functions in the package are built based on the SpatialExperiment object, allowing integration into various spatial transcriptomics-related packages from Bioconductor. After modelling density, the package allows for serveral downstream analysis, including colocalization analysis, boundary detection analysis and differential density analysis.
if (!require("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
::install("scider") BiocManager
The development version of scider
can be installed from GitHub:
::install_github("ChenLaboratory/scider") devtools
library(scider)
library(SpatialExperiment)
In this vignette, we will use a subset of a Xenium Breast Cancer dataset.
data("xenium_bc_spe")
In the data, we have quantification of 541 genes from 10000 cells.
spe
## class: SpatialExperiment
## dim: 541 10000
## metadata(0):
## assays(1): counts
## rownames(541): ENSG00000121270 ENSG00000213088 ... BLANK_0444
## BLANK_0447
## rowData names(3): ID Symbol Type
## colnames(10000): cell_212124 cell_120108 ... cell_252054 cell_568560
## colData names(21): cell_id transcript_counts ... cell_type sample_id
## reducedDimNames(0):
## mainExpName: NULL
## altExpNames(0):
## spatialCoords names(2) : x_centroid y_centroid
## imgData names(1): sample_id
We also have cell-type annotations of these cells, there are 4 cell types.
table(colData(spe)$cell_type)
##
## B cells Breast cancer Fibroblasts T cells
## 643 3550 4234 1573
We can use the function plotSpatial
to visualise the cell position and color the cells by cell types.
plotSpatial(spe, color = cell_type, alpha = 0.8)
scider
can conduct grid-based density analysis for spatial transcriptomics data.
Before calculating density, we need to define cell type-of-interest (COI). In this case, all cell types are COIs.
unique(colData(spe)$cell_type)
coi <- coi
## [1] "Fibroblasts" "Breast cancer" "T cells" "B cells"
We can perform density calculation for each COI using function gridDensity
. The calculated density and grid information are saved in the metadata of the SpatialExperimnet object.
gridDensity(spe, coi = coi)
spe <-
names(metadata(spe))
## [1] "grid_density" "grid_info"
metadata(spe)$grid_density
## DataFrame with 11400 rows and 9 columns
## x_grid y_grid node_x node_y node density_fibroblasts
## <numeric> <numeric> <integer> <integer> <character> <numeric>
## 1 329.102 203.852 1 1 1-1 0.00352639
## 2 329.102 299.810 1 2 1-2 0.00432724
## 3 329.102 395.767 1 3 1-3 0.00526027
## 4 329.102 491.725 1 4 1-4 0.00633438
## 5 329.102 587.683 1 5 1-5 0.00755759
## ... ... ... ... ... ... ...
## 11396 9865.73 10663.2 100 110 100-110 0.00743260
## 11397 9865.73 10759.2 100 111 100-111 0.00601659
## 11398 9865.73 10855.2 100 112 100-112 0.00482908
## 11399 9865.73 10951.1 100 113 100-113 0.00384286
## 11400 9865.73 11047.1 100 114 100-114 0.00303176
## density_breast_cancer density_t_cells density_b_cells
## <numeric> <numeric> <numeric>
## 1 0.000124482 0.00200091 0.00308062
## 2 0.000158866 0.00269403 0.00447254
## 3 0.000207521 0.00360691 0.00639036
## 4 0.000278528 0.00478231 0.00893371
## 5 0.000385603 0.00624991 0.01215386
## ... ... ... ...
## 11396 0.00992645 1.85862e-05 0.000385502
## 11397 0.00715312 9.95949e-06 0.000337516
## 11398 0.00504125 5.53001e-06 0.000288967
## 11399 0.00348873 3.29144e-06 0.000242472
## 11400 0.00237981 2.14802e-06 0.000199856
We can visualise the density of each COI using function plotDensity
.
plotDensity(spe, coi = coi[1])
After obtaining grid-based density for each COI, we can then detect regions-of-interest (ROIs) based on density or select by user.
To detect ROIs automatically, we can use the function findROI
.
The detected ROIs are saved in the metadata of the SpatialExperiment object.
findROI(spe, coi = coi)
spe <-
metadata(spe)$roi
## DataFrame with 1464 rows and 6 columns
## component members x y xcoord ycoord
## <factor> <character> <character> <character> <numeric> <numeric>
## 1 1 83-107 83 107 8228.13 10375.37
## 2 1 83-108 83 108 8228.13 10471.33
## 3 1 84-107 84 107 8324.46 10375.37
## 4 1 84-108 84 108 8324.46 10471.33
## 5 1 85-102 85 102 8420.79 9895.58
## ... ... ... ... ... ... ...
## 1460 29 53-104 53 104 5338.24 10087.5
## 1461 29 53-105 53 105 5338.24 10183.5
## 1462 29 53-106 53 106 5338.24 10279.4
## 1463 29 54-105 54 105 5434.57 10183.5
## 1464 29 54-106 54 106 5434.57 10279.4
We can visualise the ROIs with function plotROI
.
plotROI(spe)
Alternatively, users can select ROIs based on their own research interest (drawn by hand). This can be done using function selectRegion
. This function will open an interactive window with an interactive plot for users to zoom-in/-out and select ROI using either a rectangular or lasso selection tool. Users can also press the Export selected points
button to save the ROIs as object in the R environment.
selectRegion(metadata(spe)$grid_density, x.col = "x_grid", y.col = "y_grid")
After closing the interactive window, the selected ROI has been saved as a data.frame object named sel_region
in the R environment.
sel_region
We can then use the postSelRegion
to save the ROI in the metadata of the SpatialExperiment object.
postSelRegion(spe, sel_region = sel_region)
spe1 <-
metadata(spe1)$roi
Similarly, we can plot visualise the user-defined ROI with function plotROI
.
plotROI(spe1)
After defining ROIs, we can then test the relationship between any two cell types within each ROI or overall but account for ROI variation using a cubic spline or a linear fit.
This can be done with function corrDensity
, by setting the celltype1
and celltype2
parameters, the modelling results are saved in the metadata of the SpatialExperiment object.
corDensity(spe) model_result <-
We can see the correlation between breast cancer and fibroblasts in each ROI.
model_result
## DataFrame with 174 rows and 9 columns
## celltype1 celltype2 ROI ngrid cor.coef t
## <character> <character> <character> <numeric> <numeric> <numeric>
## 1 Fibroblasts Breast cancer 1 25 -0.4212512 -2.227535
## 2 Fibroblasts Breast cancer 2 106 -0.5961093 -7.571454
## 3 Fibroblasts Breast cancer 3 27 -0.9058793 -10.694243
## 4 Fibroblasts Breast cancer 4 42 -0.9245825 -15.348691
## 5 Fibroblasts Breast cancer 5 36 -0.0392948 -0.229303
## ... ... ... ... ... ... ...
## 170 T cells B cells 25 25 0.459082 2.478267
## 171 T cells B cells 26 29 0.865404 8.974262
## 172 T cells B cells 27 21 -0.248482 -1.118180
## 173 T cells B cells 28 38 0.628826 4.852386
## 174 T cells B cells 29 22 0.110237 0.496019
## df p.Pos p.Neg
## <numeric> <numeric> <numeric>
## 1 23 0.982010 1.79903e-02
## 2 104 1.000000 7.83173e-12
## 3 25 1.000000 4.06755e-11
## 4 40 1.000000 1.16320e-18
## 5 34 0.589996 4.10004e-01
## ... ... ... ...
## 170 23 1.04871e-02 0.989513
## 171 27 6.86205e-10 1.000000
## 172 19 8.61285e-01 0.138715
## 173 36 1.17842e-05 0.999988
## 174 20 3.12644e-01 0.687356
We can also visualise the fitting using function plotDensCor
.
plotDensCor(spe, celltype1 = "Breast cancer", celltype2 = "Fibroblasts")
Or, we can visualise the statistics between cell types using function plotModStat
with a heatmap.
plotCorHeatmap(model_result)
corDensity(spe, by.roi = FALSE)
model_result2 <-
plotCorHeatmap(model_result2)
Based on the grid density, we can ask many biological question about the data. For example, we would like to know if a certain cell type that are located in high density of breast cancer cells are different to the same cell type from a different level of breast cancer region.
To address this question, we first need to divide cells into different levels of grid density. This can be done using a contour identification strategy with function getContour
.
getContour(spe, coi = "Breast cancer") spe <-
Different level of contour can be visualised with cells using plotContour
.
plotContour(spe, coi = "Breast cancer")
We can then annotate cells by their locations within each contour using function allocateCells
.
allocateCells(spe) spe <-
plotSpatial(spe, color = breast_cancer_contour, alpha = 0.5)
We can visualise cell type composition per level.
plotCellCompo(spe, coi = "Breast cancer")
plotCellCompo(spe, coi = "Breast cancer", by.roi = TRUE)
sessionInfo()
## R version 4.4.1 (2024-06-14)
## Platform: x86_64-pc-linux-gnu
## Running under: Ubuntu 24.04.1 LTS
##
## Matrix products: default
## BLAS: /home/biocbuild/bbs-3.20-bioc/R/lib/libRblas.so
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.12.0
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_GB LC_COLLATE=C
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## time zone: America/New_York
## tzcode source: system (glibc)
##
## attached base packages:
## [1] stats4 stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] sf_1.0-18 SpatialExperiment_1.16.0
## [3] SingleCellExperiment_1.28.0 SummarizedExperiment_1.36.0
## [5] Biobase_2.66.0 GenomicRanges_1.58.0
## [7] GenomeInfoDb_1.42.0 IRanges_2.40.0
## [9] S4Vectors_0.44.0 BiocGenerics_0.52.0
## [11] MatrixGenerics_1.18.0 matrixStats_1.4.1
## [13] scider_1.4.0 ggplot2_3.5.1
##
## loaded via a namespace (and not attached):
## [1] DBI_1.2.3 deldir_2.0-4 rlang_1.1.4
## [4] magrittr_2.0.3 snakecase_0.11.1 e1071_1.7-16
## [7] compiler_4.4.1 spatstat.geom_3.3-3 mgcv_1.9-1
## [10] fftwtools_0.9-11 vctrs_0.6.5 stringr_1.5.1
## [13] pkgconfig_2.0.3 crayon_1.5.3 fastmap_1.2.0
## [16] magick_2.8.5 XVector_0.46.0 lwgeom_0.2-14
## [19] labeling_0.4.3 utf8_1.2.4 promises_1.3.0
## [22] rmarkdown_2.28 UCSC.utils_1.2.0 purrr_1.0.2
## [25] xfun_0.48 zlibbioc_1.52.0 cachem_1.1.0
## [28] jsonlite_1.8.9 goftest_1.2-3 highr_0.11
## [31] later_1.3.2 DelayedArray_0.32.0 spatstat.utils_3.1-0
## [34] R6_2.5.1 RColorBrewer_1.1-3 bslib_0.8.0
## [37] stringi_1.8.4 spatstat.data_3.1-2 spatstat.univar_3.0-1
## [40] lubridate_1.9.3 jquerylib_0.1.4 Rcpp_1.0.13
## [43] knitr_1.48 tensor_1.5 splines_4.4.1
## [46] httpuv_1.6.15 Matrix_1.7-1 igraph_2.1.1
## [49] timechange_0.3.0 tidyselect_1.2.1 abind_1.4-8
## [52] yaml_2.3.10 spatstat.random_3.3-2 spatstat.explore_3.3-3
## [55] lattice_0.22-6 tibble_3.2.1 shiny_1.9.1
## [58] withr_3.0.2 evaluate_1.0.1 isoband_0.2.7
## [61] units_0.8-5 proxy_0.4-27 polyclip_1.10-7
## [64] pillar_1.9.0 KernSmooth_2.23-24 plotly_4.10.4
## [67] generics_0.1.3 munsell_0.5.1 scales_1.3.0
## [70] xtable_1.8-4 class_7.3-22 glue_1.8.0
## [73] janitor_2.2.0 pheatmap_1.0.12 lazyeval_0.2.2
## [76] tools_4.4.1 data.table_1.16.2 grid_4.4.1
## [79] tidyr_1.3.1 colorspace_2.1-1 nlme_3.1-166
## [82] GenomeInfoDbData_1.2.13 cli_3.6.3 spatstat.sparse_3.1-0
## [85] fansi_1.0.6 S4Arrays_1.6.0 viridisLite_0.4.2
## [88] dplyr_1.1.4 gtable_0.3.6 sass_0.4.9
## [91] digest_0.6.37 classInt_0.4-10 SparseArray_1.6.0
## [94] rjson_0.2.23 htmlwidgets_1.6.4 farver_2.1.2
## [97] htmltools_0.5.8.1 lifecycle_1.0.4 httr_1.4.7
## [100] mime_0.12