# Install packages
install.packages(c("Seurat","dplyr","tidyr","readr","pheatmap"))
# Install Bioconductor packages
if (!require("BiocManager", quietly = TRUE))
install.packages("BiocManager")
::install("clusterProfiler")
BiocManager::install("org.Mm.eg.db")
BiocManager::install("org.Hs.eg.db")
BiocManager
# Install CellDART
::install_github("mexchy1000/CellDART", build_vignettes = T, force = T)
devtools
# Install STopover
::install_github("bsungwoo/STopover", build_vignettes = T, force = T) devtools
library(STopover)
library(Seurat)
#> Attaching SeuratObject
library(dplyr)
#>
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#>
#> filter, lag
#> The following objects are masked from 'package:base':
#>
#> intersect, setdiff, setequal, union
library(tidyr)
library(readr)
library(pheatmap)
# Make output folder
<- 'Results'
output_folder_name if (!file.exists(output_folder_name)){
dir.create(output_folder_name)
}
<- file.path(output_folder_name, 'figures')
fig_dir if (!file.exists(fig_dir)){
dir.create(fig_dir)
}
# Install and load environment
::install_load_env('STopover')
STopover# Import anndata
<- reticulate::import('scanpy', convert = FALSE)
sc <- reticulate::import('pandas', convert = FALSE)
pd # Import STopover
<- reticulate::import('STopover', convert = FALSE)
STopover
# Load single-cell anndata that contains only samples from 'tLung'
<- sc$read_h5ad('sc_lung_cancer.h5ad') sc_adata
# Extract metadata from anndata
<- data.frame(reticulate::py_to_r(sc_adata$obs))
metadata
# Reassign Undetermined and NaN in 'Cell_subtype' into _ns subtype
'Cell_subtype']] <- as.character(metadata[['Cell_subtype']])
metadata[['Cell_type']] <- as.character(metadata[['Cell_type']])
metadata[[<- metadata %>%
metadata ::mutate(Cell_subtype = ifelse((Cell_subtype=="Undetermined"|is.na(Cell_subtype)),
dplyrpaste0(Cell_type, "_ns"), Cell_subtype))
# Change the 'Cell_subtype' column to factor
'Cell_subtype']] <- factor(metadata[['Cell_subtype']])
metadata[[
# Update the metadata in original anndata
$obs <- reticulate::r_to_py(metadata[reticulate::py_to_r(sc_adata$obs_names$tolist()), ])
sc_adata
# Save single-cell Seurat object
$write('sc_lung_cancer_mod.h5ad') sc_adata
# Remove cell types that end with '_ns'
<- grep(levels(sp_data_cell@meta.data[['celltype']]), pattern='_ns', value=T, invert=T)
cell_types_wo_ns ::Idents(sp_data_cell) <- "celltype"
Seurat= subset(sp_data_cell, idents = cell_types_wo_ns) sp_data_cell_sub
# Visualize annotation of cells
::SpatialDimPlot(sp_data_cell_sub, pt.size.factor = 1) Seurat
# Load cell type names saved in the medatata of single-cell data
<- colnames(sp_data_grid@meta.data)[5:51]
celltype_names
# Define cell type pairs as calculated between single-cell and spatial data
<- data.frame(A=c(), B=c())
feat_pairs for (celltype_a in celltype_names){
for (celltype_b in celltype_names){
<- rbind(feat_pairs, data.frame(A=celltype_a,B=celltype_b))
feat_pairs
}
}
# Fun Stopover analysis between cancer epithelial cells and other cell types
<- STopover::topological_similarity(sp_data_grid,
sp_data_grid_celltype
feat_pairs,use_lr_db = F,
lr_db_species = "human",
min_size = 20,
fwhm = 2.5,
thres_per = 30,
assay = "Spatial",
slot = "data",
lognorm = F)
::write_rds(sp_data_grid_celltype, 'sp_data_merge_celltype.rds') readr
# Load global overlap score calculated between cancer epithelial and other cell types
<- sp_data_grid_celltype@misc %>%
df ::select(Feat_1, Feat_2, J_comp) %>%
dplyr::pivot_wider(names_from = Feat_1, values_from = J_comp) %>%
tidyr::column_to_rownames(var = "Feat_2")
tibble# Fill NA values with 0
is.na(df)] = 0
df[
# Color choices
::hcl.pals()
grDevices#> [1] "Pastel 1" "Dark 2" "Dark 3" "Set 2"
#> [5] "Set 3" "Warm" "Cold" "Harmonic"
#> [9] "Dynamic" "Grays" "Light Grays" "Blues 2"
#> [13] "Blues 3" "Purples 2" "Purples 3" "Reds 2"
#> [17] "Reds 3" "Greens 2" "Greens 3" "Oslo"
#> [21] "Purple-Blue" "Red-Purple" "Red-Blue" "Purple-Orange"
#> [25] "Purple-Yellow" "Blue-Yellow" "Green-Yellow" "Red-Yellow"
#> [29] "Heat" "Heat 2" "Terrain" "Terrain 2"
#> [33] "Viridis" "Plasma" "Inferno" "Rocket"
#> [37] "Mako" "Dark Mint" "Mint" "BluGrn"
#> [41] "Teal" "TealGrn" "Emrld" "BluYl"
#> [45] "ag_GrnYl" "Peach" "PinkYl" "Burg"
#> [49] "BurgYl" "RedOr" "OrYel" "Purp"
#> [53] "PurpOr" "Sunset" "Magenta" "SunsetDark"
#> [57] "ag_Sunset" "BrwnYl" "YlOrRd" "YlOrBr"
#> [61] "OrRd" "Oranges" "YlGn" "YlGnBu"
#> [65] "Reds" "RdPu" "PuRd" "Purples"
#> [69] "PuBuGn" "PuBu" "Greens" "BuGn"
#> [73] "GnBu" "BuPu" "Blues" "Lajolla"
#> [77] "Turku" "Hawaii" "Batlow" "Blue-Red"
#> [81] "Blue-Red 2" "Blue-Red 3" "Red-Green" "Purple-Green"
#> [85] "Purple-Brown" "Green-Brown" "Blue-Yellow 2" "Blue-Yellow 3"
#> [89] "Green-Orange" "Cyan-Magenta" "Tropic" "Broc"
#> [93] "Cork" "Vik" "Berlin" "Lisbon"
#> [97] "Tofino" "ArmyRose" "Earth" "Fall"
#> [101] "Geyser" "TealRose" "Temps" "PuOr"
#> [105] "RdBu" "RdGy" "PiYG" "PRGn"
#> [109] "BrBG" "RdYlBu" "RdYlGn" "Spectral"
#> [113] "Zissou 1" "Cividis" "Roma"
# Draw heatmap with pheatmap
<- pheatmap::pheatmap(t(df), cluster_rows=T, show_rownames=T,
out cluster_cols=T, angle_col=45, fontsize=5,
color = grDevices::hcl.colors(100, "Inferno"),
na_col = "grey70",
breaks = seq(0, 0.3, by = 0.01*0.3),
clustering_method = 'average',
clustering_distance_rows = "correlation",
clustering_distance_cols = "correlation")
<- STopover::vis_spatial_cosmx(sp_data_grid_celltype, "tS2", color_cont = "RdPu")
p1 <- STopover::vis_spatial_cosmx(sp_data_grid_celltype, "MAST", color_cont = "RdPu")
p2 + p2 p1
::vis_all_connected(sp_data_grid_celltype,
STopoverfeat_name_x = "tS2",
feat_name_y = "MAST",
slide_titles = "Lung CosMx SMI",
title_fontsize = 12,
legend_fontsize = 10,
save = F,
save_path = fig_dir,
save_name_add = paste0("_celltype"), return_plot = T,
fig_width = 5, fig_height = 5, dpi = 150)
#> The provided object is considered a cosmx dataset
::vis_jaccard_top_n_pair(sp_data_grid_celltype,
STopoverfeat_name_x = "tS2",
feat_name_y = "MAST",
top_n = 2,
slide_title = "Lung CosMx SMI",
title_fontsize = 12,
legend_fontsize = 10,
save = T,
save_path = fig_dir,
save_name_add = paste0("_celltype"),
fig_width = 4, fig_height = 4, dpi = 150)
#> The provided object is considered a cosmx dataset
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.
<- STopover::topological_similarity(sp_data_grid,
sp_data_merge_lr use_lr_db = T,
lr_db_species = "human",
min_size = 20,
fwhm = 2.5,
thres_per = 30,
assay = "Spatial",
slot = "data",
lognorm = F)
::write_rds(sp_data_merge_lr, '/home/nmadmin/DATA2/STopover_test/Results/data_analysis/sp_data_merge_lr.rds') readr
<- STopover::vis_spatial_cosmx(sp_data_merge_lr, "CD274", color_cont = "RdPu")
p1 <- STopover::vis_spatial_cosmx(sp_data_merge_lr, "PDCD1", color_cont = "RdPu")
p2 + p2 p1
::vis_all_connected(sp_data_merge_lr,
STopoverfeat_name_x = "CD274",
feat_name_y = "PDCD1",
slide_titles = "Lung CosMx SMI",
title_fontsize = 12,
legend_fontsize = 10,
save = T, slide_ncol = 2,
save_path = fig_dir,
save_name_add = paste0("_celltype"),
fig_width = 4, fig_height = 4, dpi = 150)
#> The provided object is considered a cosmx dataset
::vis_jaccard_top_n_pair(sp_data_merge_lr,
STopoverfeat_name_x = "CD274",
feat_name_y = "PDCD1",
top_n = 2,
slide_title = "Lung CosMx SMI",
title_fontsize = 10,
legend_fontsize = 12,
save = T, slide_ncol = 2, dot_size = 1.6,
save_path = fig_dir,
save_name_add = paste0("_celltype"),
fig_width = 4, fig_height = 4, dpi = 150)
#> The provided object is considered a cosmx dataset
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.
<- STopover::topological_similarity_celltype_pair(sp_data_grid,
sp_celltype_spec_lr celltype_x='tS2',
celltype_y='Cytotoxic.CD8..T',
use_lr_db=T,
lr_db_species='human',
min_size=20,
fwhm=2.5,
thres_per=30,
celltype_colname='Cell_subtype',
conda.env.name='STopover',
assay='Spatial',
slot='data',
lognorm=F,
return_result_df=T)
::write_rds(sp_celltype_spec_lr, 'sp_celltype_spec_lr.rds') readr
<- STopover::vis_spatial_cosmx(sp_celltype_spec_lr, "tS2-CD274",
p1 plot_title = "tS2: CD274", color_cont = "RdPu")
<- STopover::vis_spatial_cosmx(sp_celltype_spec_lr, "Cytotoxic.CD8..T-CD274",
p2 plot_title = "Cytotoxic CD8+ T: CD274", color_cont = "RdPu")
+ p2 p1
::vis_all_connected(sp_celltype_spec_lr,
STopoverfeat_name_x = "CD274",
feat_name_y = "PDCD1",
celltype_x='tS2',
celltype_y='Cytotoxic.CD8..T',
slide_titles = "Lung CosMx SMI",
title_fontsize = 12,
legend_fontsize = 10,
save = T, slide_ncol = 2,
save_path = fig_dir,
save_name_add = paste0("_celltype"),
fig_width = 4, fig_height = 4, dpi = 150)
#> The provided object is considered a cosmx dataset
::vis_jaccard_top_n_pair(sp_celltype_spec_lr,
STopoverfeat_name_x = "CD274",
feat_name_y = "PDCD1",
celltype_x='tS2',
celltype_y='Cytotoxic.CD8..T',
top_n = 2,
slide_title = "Lung CosMx SMI",
title_fontsize = 8,
legend_fontsize = 12,
save = T, slide_ncol = 2, dot_size = 1.6,
save_path = fig_dir,
save_name_add = paste0("_celltype"),
fig_width = 4, fig_height = 4, dpi = 150)
#> The provided object is considered a cosmx dataset
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.