1 Basics

spaSim (spatial Simulator) is a simulator of tumour immune microenvironment spatial data. It includes a family of functions to simulate a diverse set of cell localization patterns in tissues. Patterns include background cells (one cell type or multiple cell types of different proportions), tumour/immune clusters, immune rings and double immune rings and stripes (blood/lymphatic vessels).

As quantitative tools for spatial tissue image analysis have been developed and need benchmarking, simulations from spaSim can be applied to test and benchmark these tools and metrics. The output of spaSim are images in SpatialExperiment object format and can be used with SPIAT (SPIAT (Spatial Image Analysis of Tissues) also developed by our team.

1.1 Installing spaSim

spaSim is a R package available via the Bioconductor repository for packages. You can install the latest development version from Github. You can install spaSim using the following commands in your R session:

## Check that you have a valid Bioconductor installation
if (!requireNamespace("BiocManager", quietly = TRUE)) {


# install from GitHub the development version

1.2 Citing spaSim

We hope that spaSim will be useful for your research. Please use the following information to cite the package and the overall approach. Thank you!

## Citation info
#> To cite package 'spaSim' in publications use:
#>   Feng Y, Trigos A (2023). _spaSim: Spatial point data simulator for
#>   tissue images_. R package version 1.3.1,
#>   <>.
#>   Feng Y, Yang T, Zhu J, Li M, Doyle M, Ozcoban V, Bass G, Pizzolla A,
#>   Cain L, Weng S, Pasam A, Kocovski N, Huang Y, Keam S, Speed T, Neeson
#>   P, Pearson R, Sandhu S, Goode D, Trigos A (2023). "Spatial analysis
#>   with SPIAT and spaSim to characterize and simulate tissue
#>   microenvironments." _Nature Communications_, *14*(2697).
#>   doi:10.1038/s41467-023-37822-0
#>   <>.
#> To see these entries in BibTeX format, use 'print(<citation>,
#> bibtex=TRUE)', 'toBibtex(.)', or set
#> 'options(citation.bibtex.max=999)'.

2 Quick start to using spaSim

First attach the package


2.1 Simulate an individual image

In spaSim, spatial patterns are simulated on separate layers sequentially starting from ‘background cells’ which serve as the canvas for higher order structures (e.g. tumour clusters, immune clusters and immune rings can be simulated after/on top of background cells). Here we will go through each of these steps.

2.1.1 Simulate background cells

First we randomly generate the spatial locations of generic ‘background cells’ (without cell identities). The ‘background cells’ will serve as the input to the other simulation functions shown below which can assign new identities to these cells in a structured or unstructured way.

Two options are avaible for background cell simulation. We suggest simulating tumour images with a Hardcore Process (method = "Hardcore"), which is a Poisson process where events (i.e. cells) are maintained at a specific minimum distance from each other. As rHardcore from spatstat.random package deletes cells based on this requirement, our function uses a oversampling_rate to create more cells than the target number of cells (n_cells) to ensure the resulting image has the number of cells specified. If the resulting image ends up with slightly fewer cells than specified, increase the oversampling_rate argument to account for this.

For normal tissues, we suggest using option method = "Even" to simulate the background cells, where the cells approximately locate on the vertices of hexagons with a jitter that follows a uniform distribution applied. This is because normal cells tend to evenly spaced across the image.

bg <- simulate_background_cells(n_cells = 5000,
                                width = 2000,
                                height = 2000,
                                method = "Hardcore",
                                min_d = 10,
                                oversampling_rate = 1.6,
                                Cell.Type = "Others")

#>           Cell.X.Position Cell.Y.Position Cell.Type
#> Cell_55          156.3994        349.0815    Others
#> Cell_2226        878.6766        633.4749    Others
#> Cell_1113        569.0253        489.3713    Others
#> Cell_4788       1996.0439        292.1873    Others
#> Cell_4600       1756.8683       1608.0244    Others
#> Cell_951         306.1119       1641.1277    Others
# use dim(bg)[1] to check if the same number of cells are simulated. 
# if not, increase `oversampling_rate`.
#> [1] 5000

We also give an example of normal tissue simulation here. The following code is not run within this vignette.

bg_normal <- simulate_background_cells(n_cells = 5000,
                                      width = 2000,
                                      height = 2000,
                                      method = "Even",
                                      min_d = NULL,
                                      jitter = 0.3,
                                      Cell.Type = "Others")

2.1.2 Simulate mixed background

To randomly assign ‘background cells’ to the the specified cell identities in the specified proportions in an unstructured manner, spaSim includes the simulate_mixing function.

Users can use the background image they defined earlier (e.g. bg), or the image predefined in the package (bg1) as the ‘background cells’ to further construct the mixed cell identities. In this example, we use bg that was defined in the previous section.

The props argument defines the proportions of each cell type in idents. Although the proportions are specified, the exact cells that are assigned by each identity are stochastic. Therefore, users are encouraged to use the set.seed() function to ensure reproducibility.

mix_bg <- simulate_mixing(bg_sample = bg,
                          idents = c("Tumour", "Immune", "Others"),
                          props = c(0.2, 0.3, 0.5), 
                          plot_image = TRUE,
                          plot_colours = c("red","darkgreen","lightgray"))

2.1.3 Simulate clusters

This function aims to simulate cells that aggregate as clusters like tumour clusters or immune clusters. Tumour clusters can be circles or ovals (or merging several ovals/circles together), and immune clusters are irregular (or merging several irregular shapes together).

First, we specify the properties of clusters such their primary cell type, size, shape and location. If infiltrating cell types are required, we can also include their properties.

If there are multiple cell types lying in the cluster (e.g. tumour cells and infiltrating cells), the assignment of identities to these cells is random, using the random number sampling technique.

cluster_properties <- list(
  C1 =list(name_of_cluster_cell = "Tumour", size = 500, shape = "Oval", 
           centre_loc = data.frame(x = 600, y = 600),infiltration_types = c("Immune1", "Others"), 
           infiltration_proportions = c(0.1, 0.05)), 
  C2 = list(name_of_cluster_cell = "Immune1", size = 600,  shape = "Irregular", 
            centre_loc = data.frame(x = 1500, y = 500), infiltration_types = c("Immune", "Others"),
            infiltration_proportions = c(0.1, 0.05)))
# can use any defined image as background image, here we use mix_bg defined in the previous section
clusters <- simulate_clusters(bg_sample = mix_bg,
                              n_clusters = 2,
                              bg_type = "Others",
                              cluster_properties = cluster_properties,
                              plot_image = TRUE,
                              plot_categories = c("Tumour" , "Immune", "Immune1", "Others"),
                              plot_colours = c("red", "darkgreen", "darkblue", "lightgray"))