Discovery of Spatial Ecotypes from a Single Sample
Source:vignettes/SingleSample.Rmd
SingleSample.Rmd
Overview
In this tutorial, we will illustrate how to perform de novo discovery of spatially distinct cellular ecosystems (SEs) from single-cell spatial transcriptomics dataset using SpatialEcoTyper.
We will be analyzing single-cell spatial transcriptomics data from a
melanoma sample (raw data available in Vizgen’s MERSCOPE FFPE
Human Immuno-oncology). To quickly demonstrate how SpatialEcoTyper works,
we’ve selected a subset of the sample, which can be downloaded from here
.
This demo data comprises the spatial expression of 500 genes across 27,907 cells, which are categorized into ten distinct cell types: B cells, CD4+ T cells, CD8+ T cells, NK cells, plasma cells, macrophages, dendritic cells (DC), fibroblasts, endothelial cells, and the cancer cell of origin (CCOs). Given the large proportion of CCOs, and in order to reduce running time, CCOs were excluded from this demonstration.
Besides, all cells were grouped into four regions, including tumor, inner margin, outer margin, and stroma. The tumor and stroma regions were defined based on the density of CCOs. For detailed information about the tumor and stroma annotations, please refer to the CytoSPACE paper. The inner and outer margins were delineated as regions extending 250 μm inside and outside the tumor boundaries, respectively. In addition, we assessed distance of each single cell to tumor/stroma interface by computing the shortest Euclidean distance to tumor regions (or stromal regions) for cells localized in stromal region (or tumor regions). A positive distance is used for cells localized in tumor region, and a negative distance is used for cells localized in stroma region.
SpatialEcoTyper analysis requires two input data:
- gene expression matrix: rows represent gene names and columns represent cell IDs
- meta data: a data frame with at least three columns, including “X” (X-coordinate), “Y” (Y-coordinate), and “CellType” (the cell type annotation). The row names of the meta data should match the column names (cell IDs) in the expression matrix.
First load required packages for this vignette
suppressPackageStartupMessages(library(dplyr))
suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(parallel))
suppressPackageStartupMessages(library(Seurat))
suppressPackageStartupMessages(library(data.table))
suppressPackageStartupMessages(library(googledrive))
suppressPackageStartupMessages(library(R.utils))
library(SpatialEcoTyper)
Loading data
Text files as input
Download the data from Google Drive
drive_deauth() # Disable Google sign-in requirement
drive_download(as_id("13Rc5Rsu8jbnEYYfUse-xQ7ges51LcI7n"), "HumanMelanomaPatient1_subset_counts.tsv.gz", overwrite = TRUE)
drive_download(as_id("12xcZNhpT-xbhcG8kX1QAdTeM9TKeFAUW"), "HumanMelanomaPatient1_subset_scmeta.tsv", overwrite = TRUE)
Large text files can be loaded into R using the fread
function from the data.table
package.
# Load single-cell gene expression matrix. Rows represent gene names and columns represent cell IDs
scdata <- fread("HumanMelanomaPatient1_subset_counts.tsv.gz",
sep = "\t",header = TRUE, data.table = FALSE)
rownames(scdata) <- scdata[, 1] # Setting the first column as row names
scdata <- as.matrix(scdata[, -1]) # Dropping first column
head(scdata[, 1:5])
## HumanMelanomaPatient1__cell_3655 HumanMelanomaPatient1__cell_3657
## PDK4 0 1
## TNFRSF17 0 0
## ICAM3 0 0
## FAP 1 0
## GZMB 0 0
## TSC2 0 0
## HumanMelanomaPatient1__cell_3658 HumanMelanomaPatient1__cell_3660
## PDK4 1 0
## TNFRSF17 0 0
## ICAM3 0 0
## FAP 0 0
## GZMB 0 0
## TSC2 0 0
## HumanMelanomaPatient1__cell_3661
## PDK4 0
## TNFRSF17 0
## ICAM3 0
## FAP 0
## GZMB 0
## TSC2 0
# Load single-cell metadata
# Three columns are required, including "X", "Y", and "CellType"
# The row names should match the cell ids in the expression matrix
scmeta <- read.table("HumanMelanomaPatient1_subset_scmeta.tsv",
sep = "\t",header = TRUE, row.names = 1)
scmeta <- scmeta[match(colnames(scdata), rownames(scmeta)), ] # match the cell ids in scdata and scmeta
head(scmeta[, c("X", "Y", "CellType")])
## X Y CellType
## HumanMelanomaPatient1__cell_3655 1894.706 -6367.766 Fibroblast
## HumanMelanomaPatient1__cell_3657 1942.480 -6369.602 Fibroblast
## HumanMelanomaPatient1__cell_3658 1963.007 -6374.026 Fibroblast
## HumanMelanomaPatient1__cell_3660 1981.600 -6372.266 Fibroblast
## HumanMelanomaPatient1__cell_3661 1742.939 -6374.851 Fibroblast
## HumanMelanomaPatient1__cell_3663 1921.683 -6383.309 Fibroblast
Sparse matrix as input
SpatialEcoTyper
supports sparse matrix as input. Mtx files can be loaded into R using
the ReadMtx
function from the Seurat package.
drive_download(as_id("13M3xhRxp0xK9gf5F4DE9idSBFqVQIXDT"), "HumanMelanomaPatient1_subset_counts.mtx.gz", overwrite = TRUE)
drive_download(as_id("136feRaFjMtNvduLTm5xqa3WhyyoG4Xzo"), "HumanMelanomaPatient1_subset_cells.tsv.gz", overwrite = TRUE)
drive_download(as_id("13QprWzJhzzUy_w3XSrjlt9pjf2n-G7HV"), "HumanMelanomaPatient1_subset_genes.tsv.gz", overwrite = TRUE)
scdata <- ReadMtx(mtx = "HumanMelanomaPatient1_subset_counts.mtx.gz",
cells = "HumanMelanomaPatient1_subset_cells.tsv.gz",
features = "HumanMelanomaPatient1_subset_genes.tsv.gz",
feature.column = 1, cell.column = 1)
Data normalization
The gene expression data should be normalized before SpatialEcoTyper analysis. The data can be normalized using NormalizeData or SCTransform.
Here, we are normalizing using SCTransform normalization. We recommend to install the glmGamPoi package for faster computation.
if(!"glmGamPoi" %in% installed.packages()){
BiocManager::install("glmGamPoi")
}
tmpobj <- CreateSeuratObject(scdata) %>%
SCTransform(clip.range = c(-10, 10), verbose = FALSE)
seurat_version = as.integer(gsub("\\..*", "", as.character(packageVersion("SeuratObject"))))
if(seurat_version<5){
normdata <- GetAssayData(tmpobj, "data")
}else{
normdata <- tmpobj[["SCT"]]$data
}
Using NormalizeData
for the normalization:
normdata <- NormalizeData(scdata)
Preview of the sample
The SpatialView function can be used to visualize single cells in spatial space, by cell type or by region.
# Visualize the cell type annotations in the tissue
SpatialView(scmeta, by = "CellType") + scale_color_manual(values = pals::cols25())
# Visualize the regions in the tissue
SpatialView(scmeta, by = "Region") + scale_color_brewer(type = "qual", palette = "Set1")
The SpatialView function can also be used to visualize continuous characteristics, such as the minimum distance of each single cell to tumor/stroma margin. Here, positive distances indicate cells located within the tumor region, while negative distances denote cells within the stroma.
# Visualize the distance to tumor margin
SpatialView(scmeta, by = "Dist2Interface") +
scale_colour_gradient2(low = "#5e3c99", high = "#e66101",
mid = "#d9d9d9", midpoint = 0) +
labs(color = "Distance to\ntumor margin")
SE discovery using SpatialEcoTyper
The SpatialEcoTyper function is designed to identify spatial ecotypes (SEs) from single-cell spatial transcriptomics data. The workflow begins by grouping spatially co-localized single cells into microregions, where cell-type-specific gene expression profiles (GEPs) are constructed for each microregion. Spatial networks of these microregions are constructed based on their cell type-specific GEPs, merged, and clustered for identification of SEs.
Key arguments for SpatialEcoTyper
-
normdata
A matrix representing normalized gene expression data, where rows correspond to genes and columns correspond to cells. -
metadata
A data frame containing metadata associated with each cell. Must include spatial coordinates (e.g., X and Y) as well as cell type annotations. The row names must match the column names of thenormdata
. -
outprefix
Character string specifying the prefix for output file names. -
radius
Numeric specifying the radius (default: 50 µm) for defining spatial microregion. -
minibatch
Integer specifying the number of columns to process in each minibatch in the SNF analysis. Default is 5000. This option splits the matrix into smaller chunks (minibatch), thus reducing memory usage. -
ncores
Integer specifying the number of CPU cores to use for parallel processing.
You can type ?SpatialEcoTyper
to visualize the full
manual.
## This step takes ~2 minutes to complete on macOS with an Apple M1 Pro chip and 16 GB memory.
se_results <- SpatialEcoTyper(normdata, scmeta,
outprefix = "Melanoma1_subset",
radius = 50, ncores = 2)
Optimizing memory usage
For real-world single-cell ST datasets with over 100,000 cells, the
analysis can be both time- and memory-intensive. To speed up the
process, you can increase the number of cores used
(ncores
), but this will also increase memory
consumption.
If you have limited computational memory, there are several
strategies to reduce usage. One approach is to decrease the
minibatch
size and reduce the number of cores
(ncores
) allocated. However, for larger datasets, the
minimum memory requirement may remain high. Another option is to
increase the grid.size
, which reduces the number of spatial
microregions. This can significantly decrease memory usage by
downsampling the ST data, potentially excluding many cells from the
analysis though.
Interested in multicellular communities associated with specific cell types?
If you’re interested in studying multicellular communities associated
with specific cell types, you can use the
filter.region.by.celltypes
argument to focus on
microregions containing at least one cell from the specified cell types.
For example, to identify multicellular communities related to T cells,
you can use the following command.
se_results <- SpatialEcoTyper(normdata, scmeta,
outprefix = "Melanoma1_subset",
radius = 50, ncores = 2,
filter.region.by.celltypes = c("CD8T", "CD4T"))
Interested in regions with multiple cell types?
If you’re interested in regions composed of multiple cell types, you
can use the min.cts.per.region
argument to specify the
minimum number of distinct cell types required for each microregion to
be included in the analysis.
se_results <- SpatialEcoTyper(normdata, scmeta,
outprefix = "Melanoma1_subset",
radius = 50, ncores = 2,
min.cts.per.region = 2)
SpatialEcoTyper result
When the outprefix
is specified, the SpatialEcoTyper result will
be saved as a RDS file named
outprefix_SpatialEcoTyper_results.rds
. The result can be
loaded into R using readRDS
.
## drive_download(as_id("18AzHCtwwXoOM9_yRCjyfzcLQaWiQo1au"), "Melanoma1_subset_SpatialEcoTyper_results.rds", overwrite = TRUE)
se_results <- readRDS("Melanoma1_subset_SpatialEcoTyper_results.rds")
The SpatialEcoTyper result is a list that includes two key components:
- a Seurat object constructed from the integrated embedding of spatial microregions, allowing for detailed analysis and visualization of spatial architecture;
- a data frame of the single-cell metadata, which includes annotations for discovered spatial ecotypes. These annotations can be used to explore the spatial distribution and characteristics of SEs within the tissue.
# Extract the Seurat object and updated single-cell metadata
obj <- se_results$obj # A Seurat object
scmeta <- se_results$metadata # Updated single-cell meta data, with SE annotation added
head(scmeta)
## X Y CellType CellTypeName
## HumanMelanomaPatient1__cell_3655 1894.706 -6367.766 Fibroblast Fibroblasts
## HumanMelanomaPatient1__cell_3657 1942.480 -6369.602 Fibroblast Fibroblasts
## HumanMelanomaPatient1__cell_3658 1963.007 -6374.026 Fibroblast Fibroblasts
## HumanMelanomaPatient1__cell_3660 1981.600 -6372.266 Fibroblast Fibroblasts
## HumanMelanomaPatient1__cell_3661 1742.939 -6374.851 Fibroblast Fibroblasts
## HumanMelanomaPatient1__cell_3663 1921.683 -6383.309 Fibroblast Fibroblasts
## Region Dist2Interface SE
## HumanMelanomaPatient1__cell_3655 Stroma -883.1752 SE6
## HumanMelanomaPatient1__cell_3657 Stroma -894.8463 SE7
## HumanMelanomaPatient1__cell_3658 Stroma -904.1115 SE7
## HumanMelanomaPatient1__cell_3660 Stroma -907.8909 SE7
## HumanMelanomaPatient1__cell_3661 Stroma -874.2712 SE0
## HumanMelanomaPatient1__cell_3663 Stroma -903.6559 SE6
table(scmeta$SE) ## The number of cells in each SE
##
## SE0 SE1 SE2 SE3 SE4 SE5 SE6 SE7
## 2847 6724 2773 5324 1857 3285 2856 2124
Embedding of spatial architecture
The spatial microregions’ embedding can be visualized using standard
Seurat
functions such as DimPlot
and FeaturePlot
.
These visualizations help to explore the spatial organization and
heterogeneity within the tissue.
Note: The embedding and clustering results differ slightly between Seurat v4 and v5. However, the overall clustering patterns remain largely consistent, with an Adjusted Rand Index (ARI) of 0.7 for the demonstration dataset. This consistency ensures that, despite minor variations, the key biological insights are preserved across versions.
Visualizing tumor/stroma regions in the embedding
DimPlot(obj, group.by = "Region") + scale_color_brewer(type = "qual", palette = "Set1")
Visualizing the distance of microregions to tumor/stroma interface
This plot highlights the distance of each spatial microregion to the tumor/stroma interface, revealing the spatial continuum learnt by SpatialEcoTyper. Here, positive distances indicate microregions located within the tumor region, while negative distances denote microregions within the stroma.
FeaturePlot(obj, "Dist2Interface", min.cutoff = -600, max.cutoff = 600) +
scale_colour_gradient2(low = "#5e3c99", high = "#e66101", mid = "#d9d9d9", midpoint = 0)
Visualizing spatial ecotypes in the embedding
This plot visualizes the SEs within the spatial embedding. The SEs represent distinct spatial microenvironments, each with unique cellular compositions and spatial characteristics.
DimPlot(obj, group.by = "SE") + scale_color_manual(values = pals::kelly()[-1])
Visualizing the most abundant cell types in each spatial microregion
Here, we focus on visualizing the dominant cell types within each spatial microregion to highlight the characteristic cellular composition of different SEs.
DimPlot(obj, group.by = "CellType") +
scale_color_manual(values = pals::cols25())
SE characteristics
Visualizing SEs in the tissue
The spatial distribution of SEs within the tissue can be visualized using the SpatialView function. This visualization provides insights into the localization and spatial organization of different SEs across the tissue section.
SpatialView(scmeta, by = "SE")
Note: NA values in the SE annotations denote cells excluded from this analysis, due to absence of neighboring cells or an insufficient number of detected genes.
Visualizing the cell type composition of SEs
The bar plot below illustrates the cell type composition within each SE. This visualization helps to identify the dominant cell types in each SE and compare the cellular makeup across different SEs.
Visualizing the association between SEs and pre-annotated regions
This bar plot shows the relationship between SEs and pre-annotated regions, such as tumor and stroma. The proportion of each SE associated with these regions is displayed, providing insights into how SEs correspond to different tissue regions.
Visualizing the distance of SEs to tumor/stroma interface
This box plot visualizes the distribution of distances of SEs to the tumor/stroma interface. Positive distances indicate cells located within the tumor region, while negative distances denote cells within the stroma. The SEs are ordered by their median distance, highlighting their spatial localization relative to the tumor/stroma interface.
gg <- scmeta %>% filter(!is.na(SE))
## Order SEs by their distance to tumor/stroma interface
tmp <- gg %>% group_by(SE) %>% summarise(Mid = median(Dist2Interface)) %>% arrange(Mid) %>% pull(SE)
gg$SE = factor(gg$SE, levels = tmp)
ggplot(gg, aes(SE, Dist2Interface)) +
geom_boxplot() + theme_bw() + labs(y = "Distance to tumor/stroma interface (μm)")
Identification of cell-type-specific SE markers
Differential expression analysis
To identify cell-type-specific SE markers, we can perform
differential expression analysis using the presto
package. Below is an example of how to identify fibroblast-specific
markers for each SE.
if(!"presto" %in% installed.packages()){
BiocManager::install("devtools")
devtools::install_github("immunogenomics/presto")
}
library("presto")
# Ensure the normalized data is aligned with the single-cell metadata
normdata = normdata[, rownames(scmeta)]
# Perform differential expression analysis for fibroblasts across SEs
idx = which(scmeta$CellType=="Fibroblast" & !is.na(scmeta$SE))
degs = wilcoxauc(normdata[, idx], scmeta$SE[idx])
# Filter for significant markers with positive log-fold change
degs = degs %>% filter(logFC>0 & pval<0.05) %>% arrange(desc(logFC))
head(degs)
## feature group avgExpr logFC statistic auc pval
## 1 ACTA2 SE7 2.269714 1.9200869 4826706 0.7719666 6.157041e-196
## 2 PLA2G2A SE0 2.076013 1.4444331 9636530 0.8226676 0.000000e+00
## 3 PLA2G2A SE6 2.177647 1.4145934 5418244 0.7996960 2.595786e-219
## 4 PKM SE4 2.592488 1.3997410 3527900 0.8820820 1.875924e-178
## 5 FN1 SE3 3.124745 1.1463924 5771112 0.7979963 4.778744e-193
## 6 HLA-DRA SE3 1.711258 0.9756877 5434388 0.7514360 8.958194e-160
## padj pct_in pct_out
## 1 8.455670e-194 69.35897 30.37675
## 2 0.000000e+00 90.22005 34.38547
## 3 1.069464e-216 88.39390 40.08561
## 4 3.864404e-176 98.75260 81.20265
## 5 4.922107e-191 98.03922 88.25844
## 6 6.151293e-158 86.05664 43.91978
Note: The MERSCOPE data used for SE discovery includes a limited number of genes. To enhance the analysis, you can extend the differential expression analysis to the whole transcriptome by aligning scRNA-seq data to the spatial transcriptomics data via CytoSPACE.
Visualizing the expression of cell state markers
Once you’ve identified potential markers, you can visualize their expression across SEs. Below is an example using the ACTA2 gene.
## Gene expression across all SEs
gg <- scmeta[idx, ]
gg$Expression <- normdata["ACTA2", idx]
ggplot(gg, aes(SE, Expression)) + geom_boxplot() +
theme_classic(base_size = 14) + ylab("ACTA2 expression")
You can also visualize the expression of a marker (e.g., ACTA2) in the tissue.
## Visualize gene expression in spatial
gg <- scmeta
gg$Expression <- normdata["ACTA2", ]
SpatialView(gg, by = "Expression") + scale_color_viridis_c() +
labs(color = "ACTA2\nexpression")
Session info
The session info allows users to replicate the exact environment and identify potential discrepancies in package versions or configurations that might be causing problems.
## R version 4.4.1 (2024-06-14)
## Platform: aarch64-apple-darwin20
## Running under: macOS 15.1
##
## Matrix products: default
## BLAS: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.0
##
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
##
## time zone: America/Los_Angeles
## tzcode source: internal
##
## attached base packages:
## [1] parallel stats graphics grDevices utils datasets methods
## [8] base
##
## other attached packages:
## [1] presto_1.0.0 Rcpp_1.0.13 SpatialEcoTyper_1.0.0
## [4] NMF_0.28 Biobase_2.64.0 BiocGenerics_0.50.0
## [7] cluster_2.1.6 rngtools_1.5.2 registry_0.5-1
## [10] RANN_2.6.2 Matrix_1.7-0 R.utils_2.12.3
## [13] R.oo_1.26.0 R.methodsS3_1.8.2 googledrive_2.1.1
## [16] data.table_1.16.0 Seurat_5.1.0 SeuratObject_5.0.2
## [19] sp_2.1-4 ggplot2_3.5.1 dplyr_1.1.4
##
## loaded via a namespace (and not attached):
## [1] RcppAnnoy_0.0.22 splines_4.4.1
## [3] later_1.3.2 tibble_3.2.1
## [5] polyclip_1.10-7 fastDummies_1.7.4
## [7] lifecycle_1.0.4 doParallel_1.0.17
## [9] pals_1.9 globals_0.16.3
## [11] lattice_0.22-6 MASS_7.3-60.2
## [13] magrittr_2.0.3 plotly_4.10.4
## [15] sass_0.4.9 rmarkdown_2.28
## [17] jquerylib_0.1.4 yaml_2.3.10
## [19] httpuv_1.6.15 glmGamPoi_1.16.0
## [21] sctransform_0.4.1 spam_2.10-0
## [23] spatstat.sparse_3.1-0 reticulate_1.39.0
## [25] mapproj_1.2.11 cowplot_1.1.3
## [27] pbapply_1.7-2 RColorBrewer_1.1-3
## [29] maps_3.4.2 zlibbioc_1.50.0
## [31] abind_1.4-5 GenomicRanges_1.56.1
## [33] Rtsne_0.17 purrr_1.0.2
## [35] GenomeInfoDbData_1.2.12 circlize_0.4.16
## [37] IRanges_2.38.1 S4Vectors_0.42.1
## [39] ggrepel_0.9.6 irlba_2.3.5.1
## [41] listenv_0.9.1 spatstat.utils_3.1-0
## [43] goftest_1.2-3 RSpectra_0.16-2
## [45] spatstat.random_3.3-1 fitdistrplus_1.2-1
## [47] parallelly_1.38.0 DelayedMatrixStats_1.26.0
## [49] pkgdown_2.1.0 DelayedArray_0.30.1
## [51] leiden_0.4.3.1 codetools_0.2-20
## [53] tidyselect_1.2.1 shape_1.4.6.1
## [55] farver_2.1.2 UCSC.utils_1.0.0
## [57] matrixStats_1.4.1 stats4_4.4.1
## [59] spatstat.explore_3.3-2 jsonlite_1.8.8
## [61] GetoptLong_1.0.5 progressr_0.14.0
## [63] ggridges_0.5.6 survival_3.6-4
## [65] iterators_1.0.14 systemfonts_1.1.0
## [67] foreach_1.5.2 tools_4.4.1
## [69] ragg_1.3.2 ica_1.0-3
## [71] glue_1.7.0 SparseArray_1.4.8
## [73] gridExtra_2.3 xfun_0.47
## [75] MatrixGenerics_1.16.0 GenomeInfoDb_1.40.1
## [77] withr_3.0.1 BiocManager_1.30.25
## [79] fastmap_1.2.0 fansi_1.0.6
## [81] digest_0.6.37 R6_2.5.1
## [83] mime_0.12 textshaping_0.4.0
## [85] colorspace_2.1-1 scattermore_1.2
## [87] tensor_1.5 dichromat_2.0-0.1
## [89] spatstat.data_3.1-2 utf8_1.2.4
## [91] tidyr_1.3.1 generics_0.1.3
## [93] S4Arrays_1.4.1 httr_1.4.7
## [95] htmlwidgets_1.6.4 uwot_0.2.2
## [97] pkgconfig_2.0.3 gtable_0.3.5
## [99] ComplexHeatmap_2.20.0 lmtest_0.9-40
## [101] XVector_0.44.0 htmltools_0.5.8.1
## [103] dotCall64_1.1-1 clue_0.3-65
## [105] scales_1.3.0 png_0.1-8
## [107] spatstat.univar_3.0-1 knitr_1.48
## [109] rstudioapi_0.16.0 reshape2_1.4.4
## [111] rjson_0.2.22 nlme_3.1-164
## [113] curl_5.2.2 cachem_1.1.0
## [115] zoo_1.8-12 GlobalOptions_0.1.2
## [117] stringr_1.5.1 KernSmooth_2.23-24
## [119] miniUI_0.1.1.1 desc_1.4.3
## [121] pillar_1.9.0 grid_4.4.1
## [123] vctrs_0.6.5 promises_1.3.0
## [125] xtable_1.8-4 evaluate_0.24.0
## [127] cli_3.6.3 compiler_4.4.1
## [129] rlang_1.1.4 crayon_1.5.3
## [131] future.apply_1.11.2 labeling_0.4.3
## [133] plyr_1.8.9 fs_1.6.4
## [135] stringi_1.8.4 viridisLite_0.4.2
## [137] deldir_2.0-4 gridBase_0.4-7
## [139] munsell_0.5.1 lazyeval_0.2.2
## [141] spatstat.geom_3.3-2 RcppHNSW_0.6.0
## [143] patchwork_1.2.0 sparseMatrixStats_1.16.0
## [145] future_1.34.0 shiny_1.9.1
## [147] highr_0.11 SummarizedExperiment_1.34.0
## [149] ROCR_1.0-11 gargle_1.5.2
## [151] igraph_2.0.3 bslib_0.8.0