Contents

1 Installation

if (!require("BiocManager"))
    install.packages("BiocManager")
BiocManager::install("spicyR")

2 Overview

A SegmentedCells is an object designed to store data from imaging cytometry (FISH, IMC, CycIF, spatial transcriptomics, … ) that has already been segmented and reduced to individual cells. A SegmentedCells extends DataFrame and defines methods that take advantage of DataFrame nesting to represent various elements of cell-based experiments with spatial orientation that are commonly encountered. This object is able to store information on a cell’s spatial location, cellType, morphology, intensity of gene/protein marks as well as image level phenotype information. Ideally this type of data can be used for cell clustering, point process models or nearest neighbour analysis. Below we will consider a few examples of data formats that can be transformed into a SegmentedCells.

First, load the spicyR package.

library(spicyR)
library(S4Vectors)

3 Example 1 - Data resembles cellProfiler output

Here we create a SegmentedCells from data that was output from cellProfiler or similar programs. This assumes that there are columns with the string AreaShape_ and Intensity_Mean and that there are ObjectNumber and ImageNumber columns.

Here we create toy cellProfiler data.


### Something that resembles cellProfiler data

set.seed(51773)

n = 10

cells <- data.frame(row.names = seq_len(n))
cells$ObjectNumber <- seq_len(n)
cells$ImageNumber <- rep(1:2,c(n/2,n/2))
cells$AreaShape_Center_X <- runif(n)
cells$AreaShape_Center_Y <- runif(n)
cells$AreaShape_round <- rexp(n)
cells$AreaShape_diameter <- rexp(n, 2)
cells$Intensity_Mean_CD8 <- rexp(n, 10)
cells$Intensity_Mean_CD4 <- rexp(n, 10)

We can then create a SegmentedCells object.

cellExp <- SegmentedCells(cells, cellProfiler = TRUE)
#> There is no cellType column, setting to NA
cellExp
#> A SegmentedCells object with...
#> Number of images:2
#> Number of cells:10
#> Number of cell types: 1 [ NA ]
#> Number of intensities: 2 [ CD8, CD4 ]
#> Number of morphologies: 2 [ round, diameter ]
#> Number of image phenotypes: 0 [ ]

Extract the cellSummary information and overwrite it as well.

cellSum <- cellSummary(cellExp)
head(cellSum)
#> DataFrame with 6 rows and 6 columns
#>    imageID      cellID imageCellID         x         y cellType
#>   <factor> <character> <character> <numeric> <numeric> <factor>
#> 1        1      cell_1      cell_1  0.367243  0.820150       NA
#> 2        1      cell_2      cell_2  0.613818  0.846200       NA
#> 3        1      cell_3      cell_3  0.335930  0.318286       NA
#> 4        1      cell_4      cell_4  0.501737  0.373931       NA
#> 5        1      cell_5      cell_5  0.829350  0.140415       NA
#> 6        2      cell_6      cell_6  0.831271  0.175128       NA

cellSummary(cellExp) <- cellSum

We can then set the cell types of each cell by extracting and clustering marker intensity information.

markers <- cellMarks(cellExp)
kM <- kmeans(markers,2)
cellType(cellExp) <- paste('cluster',kM$cluster, sep = '')

cellSum <- cellSummary(cellExp)
head(cellSum)
#> DataFrame with 6 rows and 6 columns
#>    imageID      cellID imageCellID         x         y cellType
#>   <factor> <character> <character> <numeric> <numeric> <factor>
#> 1        1      cell_1      cell_1  0.367243  0.820150 cluster1
#> 2        1      cell_2      cell_2  0.613818  0.846200 cluster1
#> 3        1      cell_3      cell_3  0.335930  0.318286 cluster2
#> 4        1      cell_4      cell_4  0.501737  0.373931 cluster2
#> 5        1      cell_5      cell_5  0.829350  0.140415 cluster1
#> 6        2      cell_6      cell_6  0.831271  0.175128 cluster1

4 Example 2 - Three pancreatic islets from from Damond et al (2019)

Read in data.

isletFile <- system.file("extdata","isletCells.txt.gz", package = "spicyR")
cells <- read.table(isletFile, header = TRUE)

We can then create a SegmentedCells object.

cellExp <- SegmentedCells(cells, cellProfiler = TRUE)
#> There is no cellType column, setting to NA
cellExp
#> A SegmentedCells object with...
#> Number of images:1
#> Number of cells:4650
#> Number of cell types: 1 [ NA ]
#> Number of intensities: 38 [ c1, c10, ..., c9 ]
#> Number of morphologies: 15 [ Area, Compactness, ..., Solidity ]
#> Number of image phenotypes: 0 [ ]

We can then set the cell types of each cell by extracting and clustering marker intensity information.

markers <- cellMarks(cellExp)
kM <- kmeans(markers,4)
cellType(cellExp) <- paste('cluster',kM$cluster, sep = '')

cellSum <- cellSummary(cellExp)
head(cellSum)
#> DataFrame with 6 rows and 6 columns
#>    imageID      cellID imageCellID         x         y cellType
#>   <factor> <character> <character> <integer> <integer> <factor>
#> 1        1      cell_1      cell_1        53         0 cluster1
#> 2        1      cell_2      cell_2       128         0 cluster1
#> 3        1      cell_3      cell_3       135         0 cluster1
#> 4        1      cell_4      cell_4       450         0 cluster1
#> 5        1      cell_5      cell_5       458         0 cluster3
#> 6        1      cell_6      cell_6       551         0 cluster3

Here is a very simple plot in ggplot showing the spatial distribution of the cell types

plot(cellExp, imageID=1)