Skip to contents

In this tutorial, we’ll look at basic usage of the MapLabels() function for plotting features that represent discrete groups of spots. This could for example be manually selected spots or clusters. Such features as stored in the meta.data slot of our Seurat object and can be represented as either ‘character’ vectors of ‘factors’.

Load data

First we need to load some 10x Visium data. Here we’ll use a mouse brain tissue dataset and a mouse colon dataset that are shipped with semla.

# Load data
se_mbrain <- readRDS(file = system.file("extdata", 
                                        "mousebrain/se_mbrain", 
                                        package = "semla"))
se_mbrain$sample_id <- "mousebrain"
se_mcolon <- readRDS(file = system.file("extdata", 
                                        "mousecolon/se_mcolon", 
                                        package = "semla"))
se_mcolon$sample_id <- "mousecolon"
se <- MergeSTData(se_mbrain, se_mcolon)

Map categorical features

For categorical data, we use MapLabels() instead of MapFeatures(). This function allows us to color our spots based on some column of our Seurat object containing categorical data.

# Here we use the & operator from the patchwork R package to add a theme
# You can find more details in the 'advanced' tutorial
MapLabels(se, column_name = "sample_id", ncol = 1) &
  theme(legend.position = "right")

Let’s run unsupervised clustering on our data to get slightly more interesting results to work with.

NB: It doesn’t make much sense to run data-driven clustering on two completely different tissue types, but here we are only interested in demonstrating how you can use MapLabels.

se <- se |>
  NormalizeData() |>
  ScaleData() |>
  FindVariableFeatures() |>
  RunPCA() |>
  FindNeighbors(reduction = "pca", dims = 1:10) |>
  FindClusters(resolution = 0.2)
## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
## 
## Number of nodes: 5164
## Number of edges: 170850
## 
## Running Louvain algorithm...
## Maximum modularity in 10 random starts: 0.9210
## Number of communities: 5
## Elapsed time: 0 seconds

Map clusters

MapLabels(se, column_name = "seurat_clusters", ncol = 1) &
  theme(legend.position = "right")

We can also use the function MapLabelsSummary() if want to add a stacked bar plot next to the spatial plot, summarizing the percentage of spots for each cluster in the section. If you would rather view the actual spot count you can pass bar_display = "count" instead.

MapLabelsSummary(se, 
                 column_name = "seurat_clusters", 
                 ncol = 1, 
                 section_number = 1) &
  theme(legend.position = "none")

Overlay maps on images

And just as with MapFeatures, we can add our H&E images to the plots. Before we do this, we just need to load the H&E images into our Seurat object first with LoadImages.

se <- LoadImages(se, verbose = FALSE)

MapLabels(se, 
          column_name = "seurat_clusters", 
          image_use = "raw", 
          override_plot_dims = TRUE) +
  plot_layout(guides = "collect") &
  guides(fill = guide_legend(override.aes = list(size = 3), 
                             ncol = 2)) &
  theme(legend.position = "right")

Crop image

We can crop the images manually by defining a crop_area. The crop_area should be a vector of length four defining the corners of a rectangle, where the x- and y-axes are defined from 0-1.

In order to decide how this rectangle should be defined, you can get some help by adding a grid to the plot:

p <- MapLabels(se, 
               column_name = "seurat_clusters", 
               image_use = "raw", 
               pt_alpha = 0.5) &
  theme(panel.grid.major = element_line(linetype = "dashed"), axis.text = element_text())
p

Now if we want to crop out the GALT tissue in the mouse colon sample we can cut the image at left=0.45, bottom=0.55, right=0.65, top=0.7:

p <- MapLabels(se, 
               column_name = "selection", 
               image_use = "raw", 
               pt_size = 5, 
               section_number = 2, 
               crop_area = c(0.45, 0.55, 0.65, 0.7))
p

And we can patch together a nice figure showing the whole tissue and the zoom in of the GALT:

# override_plot_dims=TRUE can be used to crop the image to only
# include the region that contain spots (see 'advanced' tutorial)
p_global <- MapLabels(se, 
                      column_name = "selection", 
                      image_use = "raw",
                      pt_size = 1, 
                      section_number = 2, 
                      override_plot_dims = TRUE) &
  guides(fill = guide_legend(override.aes = list(size = 3)))

p_GALT <- MapLabels(se, 
                    column_name = "selection", 
                    image_use = "raw",  
                    pt_size = 5, 
                    section_number = 2, 
                    crop_area = c(0.45, 0.55, 0.65, 0.7)) &
  theme(plot.title = element_blank(), 
        plot.subtitle = element_blank(), 
        legend.position = "none")

(p_global / p_GALT)



Package version
  • semla: 1.1.6
Session info
## R version 4.4.0 (2024-04-24)
## Platform: aarch64-apple-darwin20
## Running under: macOS Sonoma 14.5
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.4-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.12.0
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: Europe/Stockholm
## tzcode source: internal
## 
## attached base packages:
## [1] stats     graphics  grDevices datasets  utils     methods   base     
## 
## other attached packages:
## [1] patchwork_1.3.0    tibble_3.2.1       semla_1.1.6        ggplot2_3.5.0     
## [5] dplyr_1.1.4        SeuratObject_4.1.4 Seurat_4.3.0.1    
## 
## loaded via a namespace (and not attached):
##   [1] RColorBrewer_1.1-3     rstudioapi_0.16.0      jsonlite_1.8.8        
##   [4] magrittr_2.0.3         magick_2.8.4           spatstat.utils_3.1-0  
##   [7] farver_2.1.2           rmarkdown_2.28         fs_1.6.4              
##  [10] ragg_1.3.3             vctrs_0.6.5            ROCR_1.0-11           
##  [13] spatstat.explore_3.3-2 forcats_1.0.0          htmltools_0.5.8.1     
##  [16] sass_0.4.9             sctransform_0.4.1      parallelly_1.38.0     
##  [19] KernSmooth_2.23-24     bslib_0.8.0            htmlwidgets_1.6.4     
##  [22] desc_1.4.3             ica_1.0-3              plyr_1.8.9            
##  [25] plotly_4.10.4          zoo_1.8-12             cachem_1.1.0          
##  [28] igraph_2.0.3           mime_0.12              lifecycle_1.0.4       
##  [31] pkgconfig_2.0.3        Matrix_1.7-0           R6_2.5.1              
##  [34] fastmap_1.2.0          fitdistrplus_1.2-1     future_1.34.0         
##  [37] shiny_1.9.1            digest_0.6.37          colorspace_2.1-1      
##  [40] tensor_1.5             irlba_2.3.5.1          textshaping_0.4.0     
##  [43] labeling_0.4.3         progressr_0.14.0       fansi_1.0.6           
##  [46] spatstat.sparse_3.1-0  httr_1.4.7             polyclip_1.10-7       
##  [49] abind_1.4-8            compiler_4.4.0         withr_3.0.1           
##  [52] highr_0.11             MASS_7.3-60.2          tools_4.4.0           
##  [55] lmtest_0.9-40          httpuv_1.6.15          future.apply_1.11.2   
##  [58] goftest_1.2-3          glue_1.7.0             dbscan_1.2-0          
##  [61] nlme_3.1-164           promises_1.3.0         grid_4.4.0            
##  [64] Rtsne_0.17             cluster_2.1.6          reshape2_1.4.4        
##  [67] generics_0.1.3         gtable_0.3.5           spatstat.data_3.1-2   
##  [70] tidyr_1.3.1            data.table_1.16.0      sp_2.1-4              
##  [73] utf8_1.2.4             spatstat.geom_3.3-2    RcppAnnoy_0.0.22      
##  [76] ggrepel_0.9.6          RANN_2.6.2             pillar_1.9.0          
##  [79] stringr_1.5.1          spam_2.10-0            later_1.3.2           
##  [82] splines_4.4.0          lattice_0.22-6         renv_1.0.2            
##  [85] survival_3.6-4         deldir_2.0-4           tidyselect_1.2.1      
##  [88] miniUI_0.1.1.1         pbapply_1.7-2          knitr_1.48            
##  [91] gridExtra_2.3          scattermore_1.2        xfun_0.47             
##  [94] matrixStats_1.4.1      stringi_1.8.4          lazyeval_0.2.2        
##  [97] yaml_2.3.10            evaluate_0.24.0        codetools_0.2-20      
## [100] BiocManager_1.30.25    cli_3.6.3              uwot_0.2.2            
## [103] xtable_1.8-4           reticulate_1.39.0      systemfonts_1.1.0     
## [106] munsell_0.5.1          jquerylib_0.1.4        Rcpp_1.0.13           
## [109] globals_0.16.3         spatstat.random_3.3-1  zeallot_0.1.0         
## [112] png_0.1-8              spatstat.univar_3.0-1  parallel_4.4.0        
## [115] pkgdown_2.1.0          dotCall64_1.1-1        listenv_0.9.1         
## [118] viridisLite_0.4.2      scales_1.3.0           ggridges_0.5.6        
## [121] leiden_0.4.3.1         purrr_1.0.2            rlang_1.1.4           
## [124] cowplot_1.1.3          shinyjs_2.1.0