spicyR 0.99.8
# load required packages
library(spicyR)
library(ggplot2)
This guide will provide a step-by-step guide on how mixed effects models can be applied to multiple segmented and labelled images to identify how the localisation of different cell types can change across different conditions. Here, the subject is modelled as a random effect, and the different conditions are modelled as a fixed effect.
Here, we use a melanoma image dataset with two conditions: Responders and Non-Responders. With this data set, we want to see if there are differences in how cell types are localised with respect to each other.
cells
is a segmentedCells
object containing single-cell data of 135 images from 27 subjects, with 5 images per subjects. There are 9 Non-Responder subjects and 18 Responder subjects.
location()
returns a DataFrame
object providing the location (x
and y
) and cell type (cellType
) of each cell and the image it belongs to (imageID
).
phenotype()
returns a DataFrame
object providing the corresponding subject (subject
) and condition (condition
) for each image.
data("melanomaResponders")
melanomaResponders
## A segmentedCells with...
## Number of images: 135
## Number of cells: 296523
## Number of cell types: 9 [ CD8-PD1-PDL1-, SOX10+, ..., CD8-PD1-PDL1+ ]
## Number of intensities: 0 [ ]
## Number of morphologies: 0 [ ]
## Number of image phenotypes: 3 [ imageID, condition, subject ]
location(melanomaResponders)
## DataFrame with 296523 rows and 6 columns
## imageID cellID imageCellID x y cellType
## <character> <character> <character> <numeric> <numeric> <factor>
## 1 1 cell_1 cell_1 49.5 1.25 CD8-PD1-PDL1-
## 2 1 cell_2 cell_2 85 1 CD8-PD1-PDL1-
## 3 1 cell_3 cell_3 169 1.25 SOX10+
## 4 1 cell_4 cell_4 245 1 CD8-PD1-PDL1-
## 5 1 cell_5 cell_5 291 1 SOX10+
## ... ... ... ... ... ... ...
## 296519 525 cell_176846 cell_176846 170.25 248.25 SOX10+
## 296520 525 cell_176847 cell_176847 66.5 248.75 SOX10+
## 296521 525 cell_176848 cell_176848 123 248.25 SOX10+
## 296522 525 cell_176849 cell_176849 202.5 248.25 CD8-PD1-PDL1-
## 296523 525 cell_176850 cell_176850 110.5 248.75 SOX10+
phenotype(melanomaResponders)
## DataFrame with 135 rows and 3 columns
## imageID condition subject
## <numeric> <factor> <factor>
## 1 1 Non-Responders SP12-18569
## 2 2 Non-Responders SP12-18569
## 3 3 Non-Responders SP12-18569
## 4 4 Non-Responders SP12-18569
## 5 5 Non-Responders SP12-18569
## ... ... ... ...
## 521 521 Responders SW14-18104
## 522 522 Responders SW14-18104
## 523 523 Responders SW14-18104
## 524 524 Responders SW14-18104
## 525 525 Responders SW14-18104
In this data set, cellType
can be some combination of the expression of CD8, PD1 or PDL1, or is SOX10+.
To investigate changes in colocalisation between two different cell types, we measure the level of colocalisation between two cell types by modelling with the Lcross()
function in the spatstat
package. Specifically, the mean difference between the obtained function and the theoretical function is used as a measure for the level of colocalisation. Differences of this statistic between two conditions is modelled using a weighted mixed effects model, with condition as the fixed effect and subject as the random effect.
for a specific pair of cells
Firstly, we can see whether one cell type tends to be around another cell type in one condition compared to the other. This can be done using the spicy()
function, where we include condition
, and subject
. In this example, we want to see whether or not CD8-PD1+PDL1+ cells (to
) thend to be found around CD8+PD1+PDL1- cells (from
).
spicyTestPair <- spicy(melanomaResponders,
condition = "condition",
subject = "subject",
from = "CD8+PD1+PDL1-",
to = "CD8-PD1+PDL1+")
## Calculating pairwise spatial associations
## Testing for spatial differences across conditions accounting for multiple images per subject
## boundary (singular) fit: see ?isSingular
spicyTestPair
## Number of cell type pairs: 1
## Number of differentially localised cell type pairs:
## [1] 1
top(spicyTestPair)
## intercept coefficient p.value adj.pvalue
## CD8+PD1+PDL1-_CD8-PD1+PDL1+ 16.54962 -10.04735 0.02833181 0.02833181
## from to
## CD8+PD1+PDL1-_CD8-PD1+PDL1+ CD8+PD1+PDL1- CD8-PD1+PDL1+
We obtain a spicy
object which details the results of the mixed effects modelling performed. As the coefficient
in spicyTest
is negative, we find that CD8-PD1+PDL1+ cells are more likely to be found around CD8+PD1+PDL1- cells in Non-Responders.
all pairwise cell combinations
Here, we can perform what we did above for all pairwise combinations of cell types by excluding the from
and to
parameters from spicy()
.
spicyTest <- spicy(melanomaResponders,
condition = "condition",
subject = "subject")
spicyTest
## Number of cell type pairs: 81
## Number of differentially localised cell type pairs:
## conditionResponders
## 0
top(spicyTest)
## intercept coefficient p.value adj.pvalue
## CD8-PD1+PDL1+_CD8+PD1+PDL1- 21.403625 -14.143257 0.006696371 0.3184453
## CD8+PD1+PDL1-_CD8-PD1+PDL1+ 21.300751 -13.854313 0.007862848 0.3184453
## CD8-PD1+PDL1-_CD8+PD1-PDL1+ 6.348714 -7.144476 0.076475111 0.9174987
## CD8-PD1+PDL1-_CD8-PD1+PDL1+ 12.485009 -7.625312 0.081119183 0.9174987
## CD8+PD1-PDL1-_CD8+PD1-PDL1- 20.934811 -11.403936 0.093658867 0.9174987
## CD8-PD1+PDL1+_CD8-PD1+PDL1- 11.621590 -6.942920 0.112733933 0.9174987
## CD8+PD1-PDL1+_CD8-PD1+PDL1- 4.821599 -6.028484 0.119793885 0.9174987
## CD8+PD1-PDL1-_CD8+PD1+PDL1- 11.049319 7.124038 0.123391930 0.9174987
## CD8-PD1-PDL1-_CD8+PD1-PDL1- 9.067690 -2.765159 0.141393584 0.9174987
## CD8+PD1+PDL1-_CD8+PD1-PDL1- 11.041912 6.860201 0.143290192 0.9174987
## from to
## CD8-PD1+PDL1+_CD8+PD1+PDL1- CD8-PD1+PDL1+ CD8+PD1+PDL1-
## CD8+PD1+PDL1-_CD8-PD1+PDL1+ CD8+PD1+PDL1- CD8-PD1+PDL1+
## CD8-PD1+PDL1-_CD8+PD1-PDL1+ CD8-PD1+PDL1- CD8+PD1-PDL1+
## CD8-PD1+PDL1-_CD8-PD1+PDL1+ CD8-PD1+PDL1- CD8-PD1+PDL1+
## CD8+PD1-PDL1-_CD8+PD1-PDL1- CD8+PD1-PDL1- CD8+PD1-PDL1-
## CD8-PD1+PDL1+_CD8-PD1+PDL1- CD8-PD1+PDL1+ CD8-PD1+PDL1-
## CD8+PD1-PDL1+_CD8-PD1+PDL1- CD8+PD1-PDL1+ CD8-PD1+PDL1-
## CD8+PD1-PDL1-_CD8+PD1+PDL1- CD8+PD1-PDL1- CD8+PD1+PDL1-
## CD8-PD1-PDL1-_CD8+PD1-PDL1- CD8-PD1-PDL1- CD8+PD1-PDL1-
## CD8+PD1+PDL1-_CD8+PD1-PDL1- CD8+PD1+PDL1- CD8+PD1-PDL1-
Again, we obtain a spicy
object which outlines the result of the mixed effects models performed for each pairwise combination if cell types.
We can represent this as a heatmap using the spatialMEMMultiPlot()
function by providing it the spicy
object obtained.
signifPlot(spicyTest, breaks=c(-3, 3, 0.5))
There are multiple ways for calculating p-values for mixed effects models. We have also implemented a bootstrapping approach. All that is needed is a choice for the number of resamples used in the bootstrap which can be set with the nsim
parameter in spicy()
.
spicyTestBootstrap <- spicy(melanomaResponders,
condition = "condition",
subject = "subject",
nsim = 199)
spicyTestBootstrap
## Number of cell type pairs: 81
## Number of differentially localised cell type pairs:
## conditionResponders
## 14
top(spicyTestBootstrap)
## intercept coefficient p.value adj.pvalue
## CD8+PD1+PDL1+_SOX10+ -1.849790 -2.277733 0 0
## CD8+PD1+PDL1-_CD8+PD1+PDL1- 20.643857 -9.966505 0 0
## CD8+PD1-PDL1-_CD8+PD1+PDL1- 11.049319 7.124038 0 0
## CD8-PD1+PDL1+_CD8+PD1+PDL1- 21.403625 -14.143257 0 0
## CD8+PD1+PDL1+_CD8-PD1+PDL1- 6.579050 -2.957959 0 0
## CD8-PD1+PDL1+_CD8-PD1+PDL1- 11.621590 -6.942920 0 0
## CD8+PD1-PDL1+_CD8-PD1+PDL1- 4.821599 -6.028484 0 0
## CD8-PD1-PDL1+_CD8-PD1+PDL1- 4.438305 -2.245794 0 0
## CD8+PD1+PDL1-_CD8+PD1-PDL1- 11.041912 6.860201 0 0
## SOX10+_CD8+PD1+PDL1+ -1.401554 -2.184938 0 0
## from to
## CD8+PD1+PDL1+_SOX10+ CD8+PD1+PDL1+ SOX10+
## CD8+PD1+PDL1-_CD8+PD1+PDL1- CD8+PD1+PDL1- CD8+PD1+PDL1-
## CD8+PD1-PDL1-_CD8+PD1+PDL1- CD8+PD1-PDL1- CD8+PD1+PDL1-
## CD8-PD1+PDL1+_CD8+PD1+PDL1- CD8-PD1+PDL1+ CD8+PD1+PDL1-
## CD8+PD1+PDL1+_CD8-PD1+PDL1- CD8+PD1+PDL1+ CD8-PD1+PDL1-
## CD8-PD1+PDL1+_CD8-PD1+PDL1- CD8-PD1+PDL1+ CD8-PD1+PDL1-
## CD8+PD1-PDL1+_CD8-PD1+PDL1- CD8+PD1-PDL1+ CD8-PD1+PDL1-
## CD8-PD1-PDL1+_CD8-PD1+PDL1- CD8-PD1-PDL1+ CD8-PD1+PDL1-
## CD8+PD1+PDL1-_CD8+PD1-PDL1- CD8+PD1+PDL1- CD8+PD1-PDL1-
## SOX10+_CD8+PD1+PDL1+ SOX10+ CD8+PD1+PDL1+
signifPlot(spicyTestBootstrap, breaks=c(-3, 3, 0.5))
Indeed, we get improved statistical power compared to the previous method.