4 Preprocessing Xenium
library(tidyverse)
library(Seurat)
library(future)
library(qs)
library(SingleR)
library(harmony)
library(scider)
library(SpatialExperiment)
library(FNN)
4.1 Set basic ggplot2 themes for all plots and cell type colours
blank_theme <- theme_bw(base_size = 7)+
theme(panel.grid=element_blank(),
strip.background = element_blank(),
plot.title = element_text(size=7))
plan("multisession", workers = 10)
options(future.globals.maxSize = 12000 * 1024^2)
cell_types <- c("Epi", "Plasma", "Fibro", "Peri", "Macro", "Granulo", "TCD4", "SmoothMuscle", "Endo",
"B", "DC", "ILC", "Schwann", "Mast", "Mono", "TCD8", "NK", "TZBTB16", "Tgd","QC_fail")
colors <- c("#DEA0FD", "green", "#f99379", "yellowgreen","#654522" ,"#dcd300", "#fdbf6f", "#b2df8a" ,"#CC79A7","#cab2d6",
"#6a3d9a", "#1f78b4", "#85660D", "#2b3d26","#D55E00", "#a6cee3","darkblue","lightpink", "#1C7F93",
"grey")
cell_type_colors <- setNames(colors, cell_types)
4.2 Grab the data from 10x
curl -O https://cf.10xgenomics.com/samples/xenium/2.0.0/Xenium_V1_Human_Colon_Cancer_P2_CRC_Add_on_FFPE/Xenium_V1_Human_Colon_Cancer_P2_CRC_Add_on_FFPE_outs.zip
tar -xvf cell_feature_matrix.tar.gz
4.5 Load the Xenium data
xenium.obj <- LoadXenium(path, fov = "fov")
4.6 Remove cells with 0 counts
xenium.obj <- subset(xenium.obj, subset = nCount_Xenium > 0)
4.8 Look at some attributes of the Seurat object
xenium.obj@assays$Xenium$counts[1:5,1:5]
rownames(xenium.obj)
4.9 Look at some key CRC markers on the slide image
ImageDimPlot(xenium.obj, fov = "fov", molecules = c("PIGR", "LGR5", "GUCA2A", "GUCA2B", "OLFM4", "TGFBI"),axes = TRUE, nmols = 20000)
4.11 Visualise cropped area with cell segmentations & selected molecules
DefaultBoundary(xenium.obj[["zoom"]]) <- "segmentation"
ImageDimPlot(xenium.obj, fov = "zoom", axes = TRUE, border.color = "white", border.size = 0.1,
coord.fixed = FALSE, molecules = c("PIGR", "LGR5", "GUCA2A", "GUCA2B", "OLFM4", "TGFBI"), nmols = 10000)
cropped.cells <- xenium.obj@images$zoom$centroids@cells
cropped.obj <- subset(xenium.obj, cells = cropped.cells)
4.12 Calculate the MAD values for counts features
md <- cropped.obj@meta.data%>%
rownames_to_column("Barcode")%>%
mutate(m = median(nFeature_Xenium))%>%
mutate(s = mad(nFeature_Xenium))%>%
mutate(robzscore_nFeature_Xenium = abs((nFeature_Xenium - m) / (s)))%>%
mutate(m = median(nCount_Xenium))%>%
mutate(s = mad(nCount_Xenium))%>%
mutate(robzscore_nCount_Xenium = abs((nCount_Xenium - m) / (s)))%>%
ungroup()%>%
data.frame()
4.13 Reset the rownames
rownames(md) <- md$Barcode
cropped.obj@meta.data <- md
4.14 Subset based on robust Z score cutoffs
min_QC_robz <- 3
VlnPlot(cropped.obj, features = c("nCount_Xenium", "robzscore_nFeature_Xenium", "robzscore_nCount_Xenium"),
pt.size = -1)
dim(cropped.obj)
cropped.obj <- subset(cropped.obj, subset = robzscore_nFeature_Xenium < min_QC_robz & robzscore_nCount_Xenium < min_QC_robz & nCount_Xenium > 20)
VlnPlot(cropped.obj, features = c("nCount_Xenium", "robzscore_nFeature_Xenium", "robzscore_nCount_Xenium"), pt.size = -1)
dim(cropped.obj)