4 Preprocessing Xenium

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.3 Set output directory

outdir <- "/pvol/andrew/projects/spatial/TenX_CRC_paper/Xenium/output/"

4.4 Set slide path

path <- "/pvol/andrew/projects/spatial/TenX_CRC_paper/Xenium/Sample_P1/"

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.7 Plot the raw counts

VlnPlot(xenium.obj, features = c("nFeature_Xenium", "nCount_Xenium"), ncol = 2, pt.size = 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.10 Get a small subset of the data

cropped.coords <- Crop(xenium.obj[["fov"]], x = c(100,2000), y = c(5000, 6000), coords = "plot")
xenium.obj[["zoom"]] <- cropped.coords

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)