Statial
features to patient groups or outcomes.# Loading required packages
library(Statial)
library(spicyR)
library(ClassifyR)
library(lisaClust)
library(dplyr)
library(SingleCellExperiment)
library(ggplot2)
library(ggsurvfit)
library(survival)
library(tibble)
theme_set(theme_classic())
nCores <- 1
# Install the package from Bioconductor
if (!requireNamespace("BiocManager", quietly = TRUE)) {
install.packages("BiocManager")
}
BiocManager::install("Statial")
There are over 37 trillion cells in the human body, each taking up different forms and functions. The behaviour of these cells can be described by canonical characteristics, but their functions can also dynamically change based on their environmental context, leading to cells with diverse states. Understanding changes in cell state and the interplay between cells is key to understanding their mechanisms of action and how they contribute to human disease. Statial
is a suite of functions for identifying changes in cell state. This guide will provide a step-by-step overview of some key functions within Statial
.
In the following we will analyse breast cancer data from Keren et al. 2018. These images are stored in a SingleCellExperiment
object. This object contains 57811 cells across 10 images and includes information on cell type and patient survival.
Note: The original dataset was reduced down from 41 images to 10 images for the purposes of this vignette, due to size restrictions.
# Load head and neck data
data("kerenSCE")
kerenSCE
#> class: SingleCellExperiment
#> dim: 48 57811
#> metadata(0):
#> assays(1): intensities
#> rownames(48): Na Si ... Ta Au
#> rowData names(0):
#> colnames(57811): 1 2 ... 171281 171282
#> colData names(8): x y ... Survival_days_capped Censored
#> reducedDimNames(0):
#> mainExpName: NULL
#> altExpNames(0):
Kontextual
is a method to evaluate the localisation relationship between two cell types in an image. Kontextual
builds on the L-function by contextualising the relationship between two cell types in reference to the typical spatial behaviour of a \(3^{rd}\) cell type/population. By taking this approach, Kontextual
is invariant to changes in the window of the image as well as tissue structures which may be present.
The definitions of cell types and cell states are somewhat ambiguous, cell types imply well defined groups of cells that serve different roles from one another, on the other hand cell states imply that cells are a dynamic entity which cannot be discretised, and thus exist in a continuum. For the purposes of using Kontextual
we treat cell states as identified clusters of cells, where larger clusters represent a “parent” cell population, and finer sub-clusters representing a “child” cell population. For example a CD4 T cell may be considered a child to a larger parent population of Immune cells. Kontextual
thus aims to see how a child population of cells deviate from the spatial behaviour of their parent population, and how that influences the localisation between the child cell state and another cell state.
The first step in analysing these images is to organise all the cells present into cell state populations or clusters, e.g. all the different B cell types are put in a vector called bcells.
# Examine all cell types in image
unique(kerenSCE$cellType)
#> [1] "Keratin_Tumour" "CD3_Cell" "B" "CD4_Cell"
#> [5] "Dc/Mono" "Unidentified" "Macrophages" "CD8_Cell"
#> [9] "other immune" "Endothelial" "Mono/Neu" "Mesenchymal"
#> [13] "Neutrophils" "NK" "Tumour" "DC"
#> [17] "Tregs"
# Set up cell populations
tumour <- c("Keratin_Tumour", "Tumour")
bcells <- c("B")
tcells <- c("CD3_Cell", "CD4_Cell", "CD8_Cell", "Tregs")
myeloid <- c("Dc/Mono", "DC", "Mono/Neu", "Macrophages", "Neutrophils")
endothelial <- c("Endothelial")
mesenchymal <- c("Mesenchymal")
tissue <- c(endothelial, mesenchymal)
immune <- c(bcells, tcells, myeloid, "NK", "other immune") # NK = Natural Killer cells
all <- c(tumour, tissue, immune, "Unidentified")
Kontextual
accepts a SingleCellExperiment
object, or a single image, or list of images from a SingleCellExperiment
object, this gets passed into the cells
argument. The two cell types which will be evaluated are specified in the to
and from
arguments. A parent population must also be specified in the parent
argument, note the parent cell population must include the to
cell type. The argument r
will specify the radius which the cell relationship will be evaluated on. Kontextual
supports parallel processing, the number of cores can be specified using the cores
argument. Kontextual
can take a single value or multiple values for each argument and will test all combinations of the arguments specified.
Here we examine image 6 from the Keren et al. dataset where the relationship between 2 cell types depends on a parent cell population. In the image below we can see that p53
and Immune
are dispersed. However when the behaviour of p53
is placed in the context of the spatial behaviour of its parent population Keratin+Tumour
, p53
and Immune
now appear localised.
#Select image 6 from the kerenSCE dataset
kerenImage6 = kerenSCE[, kerenSCE$imageID =="6"]
#Select for all cells that express higher than baseline level of p53
p53Pos = assay(kerenImage6)["p53",] |>
as.numeric() > -0.300460
kerenImage6$cellType[p53Pos & kerenImage6$cellType %in% c("Keratin_Tumour")] <- "p53+Tumour"
#Group all immune cells under the name "Immune"
kerenImage6$cellType[kerenImage6$cellType %in% immune] <- "Immune"
kerenImage6 |>
colData() %>%
as.data.frame() %>%
filter(cellType %in% c("Keratin_Tumour", "Immune", "p53+Tumour")) %>%
arrange(cellType) %>%
ggplot(aes(x = x, y = y, color = cellType)) +
geom_point(size = 1) +
scale_colour_manual(values = c("#505050", "#D6D6D6", "#64BC46"))