# Clustering of Local Indicators of Spatial Assocation (LISA) curves
Date: 2022-11-01

Nicolas Canete1* and Ellis Patrick1,2**

1Westmead Institute for Medical Research, University of Sydney, Australia
2School of Mathematics and Statistics, University of Sydney, Australia

* nicolas.canete@sydney.edu.au
** ellis.patrick@sydney.edu.au

#### 1 November 2022

#### Package

spicyR 1.10.0

# Contents

# 1 Installation

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

    # load required packages
    library(lisaClust)
    library(spicyR)
    library(ggplot2)
    library(SingleCellExperiment)

# 2 Overview

Clustering local indicators of spatial association (LISA) functions is a methodology for identifying consistent spatial organisation of multiple cell-types in an unsupervised way. This can be used to enable the characterization of interactions between multiple cell-types simultaneously and can complement traditional pairwise analysis. In our implementation our LISA curves are a localised summary of an L-function from a Poisson point process model. Our framework `lisaClust` can be used to provide a high-level summary of cell-type colocalization in high-parameter spatial cytometry data, facilitating the identification of distinct tissue compartments or identification of complex cellular microenvironments.

# 3 Quick start

## 3.1 Generate toy data

TO illustrate our `lisaClust` framework, here we consider a very simple toy example where two cell-types are completely separated spatially. We simulate data for two different images.

    set.seed(51773)
    x <- round(c(runif(200),runif(200)+1,runif(200)+2,runif(200)+3,
               runif(200)+3,runif(200)+2,runif(200)+1,runif(200)),4)*100
    y <- round(c(runif(200),runif(200)+1,runif(200)+2,runif(200)+3,
                 runif(200),runif(200)+1,runif(200)+2,runif(200)+3),4)*100
    cellType <- factor(paste('c',rep(rep(c(1:2),rep(200,2)),4),sep = ''))
    imageID <- rep(c('s1', 's2'),c(800,800))

    cells <- data.frame(x, y, cellType, imageID)

    ggplot(cells, aes(x,y, colour = cellType)) + geom_point() + facet_wrap(~imageID)

## 3.2 Create SegmentedCellExperiment object

First we store our data in a `SegmentedCells` object.

    cellExp <- SegmentedCells(cells, cellTypeString = 'cellType')

## 3.3 Running lisaCLust

We can then use a convience function `lisaClust` to simultaneously calculate local indicators of spatial association (LISA) functions using the `lisa` function and perform k-means clustering.

    cellExp <- lisaClust(cellExp, k = 2)

## 3.4 Plot identified regions

The `hatchingPlot` function can be used to construct a `ggplot` object where the regions are marked by different hatching patterns. This allows us to plot both regions and cell-types on the same visualization.

    hatchingPlot(cellExp, useImages = c('s1','s2'))

## 3.5 Using other clustering methods.

While the `lisaClust` function is convenient, we have not implemented an exhaustive suite of clustering methods as it is very easy to do this yourself. There are just two simple steps.

### 3.5.1 Generate LISA curves

We can calculate local indicators of spatial association (LISA) functions using the `lisa` function. Here the LISA curves are a localised summary of an L-function from a Poisson point process model. The radii that will be calculated over can be set with `Rs`.

    lisaCurves <- lisa(cellExp, Rs = c(20, 50, 100))

### 3.5.2 Perform some clustering

The LISA curves can then be used to cluster the cells. Here we use k-means clustering, other clustering methods like SOM could be used. We can store these cell clusters or cell “regions” in our `SegmentedCells` object using the `cellAnnotation() <-` function.

    kM <- kmeans(lisaCurves,2)
    cellAnnotation(cellExp, "region") <- paste('region',kM$cluster,sep = '_')

## 3.6 Alternative hatching plot

We could also create this plot using `geom_hatching` and `scale_region_manual`.

    df <- as.data.frame(cellSummary(cellExp))

    p <- ggplot(df,aes(x = x,y = y, colour = cellType, region = region)) +
      geom_point() +
      facet_wrap(~imageID) +
      geom_hatching(window = "concave",
                    line.spacing = 11,
                    nbp = 50,
                    line.width = 2,
                    hatching.colour = "gray20",
                    window.length = NULL) +
      theme_minimal() +
      scale_region_manual(values = 6:7, labels = c('ab','cd'))

    p

## Faster ploting

The `hatchingPlot` can be quite slow for large images and high `nbp` or `linewidth`. It is often useful to simply plot the regions without the cell type information.

    df <- as.data.frame(cellSummary(cellExp))
    df <- df[df$imageID == "s1", ]

    p <- ggplot(df,aes(x = x,y = y, colour  = region)) +
      geom_point() +
      theme_classic()
    p

# 4 Using a SingleCellExperiment

The `lisaClust` function also works with a `SingleCellExperiment`. First lets create a `SingleCellExperiment` object.

    sce <- SingleCellExperiment(colData = cellSummary(cellExp))

`lisaClust` just needs columns in `colData` corresponding to the x and y coordinates of the cells, a column annotating the cell types of the cells and a column indicating which image each cell came from.

    sce <- lisaClust(sce,
                     k = 2,
                     spatialCoords = c("x", "y"),
                     cellType = "cellType",
                     imageID = "imageID")

We can then plot the regions using the following.

    hatchingPlot(sce)

# 5 Damond et al. islet data.

Here we apply our `lisaClust` framework to three images of pancreatic islets from A Map of Human Type 1 Diabetes Progression by Imaging Mass Cytometry by Damond et al. (2019).

## 5.1 Read in data

We will start by reading in the data and storing it as a `SegmentedCells` object. Here the data is in a format consistent with that outputted by CellProfiler.

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

## 5.2 Cluster cell-types

This data does not include annotation of the cell-types of each cell. Here we extract the marker intensities from the `SegmentedCells` object using `cellMarks`. We then perform k-means clustering with eight clusters and store these cell-type clusters in our `SegmentedCells` object using `cellType() <-`.

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

## 5.3 Generate LISA curves

As before, we can calculate perform k-means clustering on the local indicators of spatial association (LISA) functions using the `lisaClust` function.

    cellExp <- lisaClust(cellExp, k = 2, Rs = c(10,20,50))

These regions are stored in cellExp and can be extracted.

    cellAnnotation(cellExp, "region") |>
      head()
    ## [1] "region_1" "region_1" "region_1" "region_1" "region_1" "region_1"

## 5.4 Examine cell type enrichment

We should check to see which cell types appear more frequently in each region than expected by chance.

    regionMap(cellExp, type = "bubble")

## 5.5 Plot identified regions

Finally, we can use `hatchingPlot` to construct a `ggplot` object where the regions are marked by different hatching patterns. This allows us to visualize the two regions and ten cell-types simultaneously.

    hatchingPlot(cellExp)

# 6 sessionInfo()

    sessionInfo()
    ## R version 4.2.1 (2022-06-23)
    ## Platform: x86_64-pc-linux-gnu (64-bit)
    ## Running under: Ubuntu 20.04.5 LTS
    ##
    ## Matrix products: default
    ## BLAS:   /home/biocbuild/bbs-3.16-bioc/R/lib/libRblas.so
    ## LAPACK: /home/biocbuild/bbs-3.16-bioc/R/lib/libRlapack.so
    ##
    ## locale:
    ##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C
    ##  [3] LC_TIME=en_GB              LC_COLLATE=C
    ##  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8
    ##  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C
    ##  [9] LC_ADDRESS=C               LC_TELEPHONE=C
    ## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
    ##
    ## attached base packages:
    ## [1] stats4    stats     graphics  grDevices utils     datasets  methods
    ## [8] base
    ##
    ## other attached packages:
    ##  [1] SingleCellExperiment_1.20.0 SummarizedExperiment_1.28.0
    ##  [3] Biobase_2.58.0              GenomicRanges_1.50.0
    ##  [5] GenomeInfoDb_1.34.0         IRanges_2.32.0
    ##  [7] S4Vectors_0.36.0            BiocGenerics_0.44.0
    ##  [9] MatrixGenerics_1.10.0       matrixStats_0.62.0
    ## [11] ggplot2_3.3.6               spicyR_1.10.0
    ## [13] lisaClust_1.6.0             BiocStyle_2.26.0
    ##
    ## loaded via a namespace (and not attached):
    ##   [1] SpatialExperiment_1.8.0   minqa_1.2.5
    ##   [3] colorspace_2.0-3          rjson_0.2.21
    ##   [5] deldir_1.0-6              ellipsis_0.3.2
    ##   [7] class_7.3-20              scuttle_1.8.0
    ##   [9] XVector_0.38.0            fftwtools_0.9-11
    ##  [11] spatstat.data_3.0-0       farver_2.1.1
    ##  [13] fansi_1.0.3               codetools_0.2-18
    ##  [15] splines_4.2.1             R.methodsS3_1.8.2
    ##  [17] sparseMatrixStats_1.10.0  cachem_1.0.6
    ##  [19] knitr_1.40                polyclip_1.10-4
    ##  [21] jsonlite_1.8.3            nloptr_2.0.3
    ##  [23] R.oo_1.25.0               pheatmap_1.0.12
    ##  [25] ggforce_0.4.1             HDF5Array_1.26.0
    ##  [27] spatstat.sparse_3.0-0     BiocManager_1.30.19
    ##  [29] compiler_4.2.1            dqrng_0.3.0
    ##  [31] assertthat_0.2.1          Matrix_1.5-1
    ##  [33] fastmap_1.1.0             limma_3.54.0
    ##  [35] cli_3.4.1                 tweenr_2.0.2
    ##  [37] htmltools_0.5.3           tools_4.2.1
    ##  [39] lmerTest_3.1-3            gtable_0.3.1
    ##  [41] glue_1.6.2                GenomeInfoDbData_1.2.9
    ##  [43] dplyr_1.0.10              V8_4.2.1
    ##  [45] Rcpp_1.0.9                jquerylib_0.1.4
    ##  [47] vctrs_0.5.0               rhdf5filters_1.10.0
    ##  [49] nlme_3.1-160              DelayedMatrixStats_1.20.0
    ##  [51] spatstat.random_3.0-0     xfun_0.34
    ##  [53] stringr_1.4.1             beachmat_2.14.0
    ##  [55] lme4_1.1-31               lifecycle_1.0.3
    ##  [57] goftest_1.2-3             scam_1.2-13
    ##  [59] edgeR_3.40.0              zlibbioc_1.44.0
    ##  [61] MASS_7.3-58.1             scales_1.2.1
    ##  [63] spatstat.core_2.4-4       spatstat.utils_3.0-1
    ##  [65] parallel_4.2.1            rhdf5_2.42.0
    ##  [67] RColorBrewer_1.1-3        curl_4.3.3
    ##  [69] yaml_2.3.6                sass_0.4.2
    ##  [71] rpart_4.1.19              stringi_1.7.8
    ##  [73] highr_0.9                 boot_1.3-28
    ##  [75] BiocParallel_1.32.0       rlang_1.0.6
    ##  [77] pkgconfig_2.0.3           bitops_1.0-7
    ##  [79] evaluate_0.17             lattice_0.20-45
    ##  [81] purrr_0.3.5               tensor_1.5
    ##  [83] Rhdf5lib_1.20.0           labeling_0.4.2
    ##  [85] tidyselect_1.2.0          magrittr_2.0.3
    ##  [87] bookdown_0.29             R6_2.5.1
    ##  [89] magick_2.7.3              generics_0.1.3
    ##  [91] DelayedArray_0.24.0       DBI_1.1.3
    ##  [93] pillar_1.8.1              withr_2.5.0
    ##  [95] mgcv_1.8-41               abind_1.4-5
    ##  [97] RCurl_1.98-1.9            tibble_3.1.8
    ##  [99] DropletUtils_1.18.0       utf8_1.2.2
    ## [101] spatstat.geom_3.0-3       rmarkdown_2.17
    ## [103] locfit_1.5-9.6            grid_4.2.1
    ## [105] data.table_1.14.4         digest_0.6.30
    ## [107] tidyr_1.2.1               numDeriv_2016.8-1.1
    ## [109] R.utils_2.12.1            munsell_0.5.0
    ## [111] concaveman_1.1.0          bslib_0.4.0