Introduction

Slingshot(Street et al. 2018) is a popular and powerful trajectory inference tool, available from bioconductor. While it only provides default plotting functions in base R, the package also offer conversion functions that can be used to generate plots with ggplot2(Wickham 2016).

We will assume that you are both familiar with slingshot and ggplot2. Otherwise, please refere to the respective packages’ vignettes.

Running slingshots

We run slingshot on the provided example

# Running slinghsot
suppressPackageStartupMessages(library(slingshot))
data("slingshotExample")
rd <- slingshotExample$rd
colnames(rd) <- c("Dim1", "Dim2")
cl <- slingshotExample$cl
df <- data.frame(rd, "cl" = as.character(cl))
sds <- slingshot(rd, cl)

We can then visualize the samples in reduced dimension.

suppressPackageStartupMessages(library(ggplot2))
suppressPackageStartupMessages(library(dplyr))
# Plotting the results
p <- ggplot(df, aes(x = Dim1, y = Dim2)) +
  geom_point(aes(fill = cl), col = "grey70", shape = 21) + 
  theme_classic()
p

Adding the curves to a ggplot2 object

Then, we can add the curves. We can extract the needed information using the accessory functions. This can be turned into tidy data.frames that interact nicely with ggplot2 by setting the as.df argument to TRUE.

curves <- slingCurves(sds, as.df = TRUE)
p + geom_path(data = curves %>% arrange(Order),
              aes(group = Lineage)) 

We can do all the usual ggplot2 operations

p + geom_path(data = curves %>% arrange(Order),
              aes(group = Lineage), size = 1.5) 
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

p + geom_path(data = curves %>% arrange(Order),
              aes(group = Lineage, col = as.character(Lineage)), size = 1.5) 

Showing the minimum spanning tree

slingshot relies on a minimum spanning tree to build the lineages. We can extract the information via:

mst <- slingMST(sds, as.df = TRUE)

We can then plot the nodes of the graph

p + geom_point(data = mst, size = 4)

And then add the edges

p + geom_point(data = mst, size = 4) +
  geom_path(data = mst %>% arrange(Order), aes(group = Lineage), size = 2)

Building on existing tools

ggplot2 objects are very versatile. It is therefore quite easy to add the slingshot information to the output of a function that returns such an object. Here we demonstrate with the plotReducedDim function from the scater package(McCarthy et al. 2017).

suppressPackageStartupMessages(library(scater))
suppressPackageStartupMessages(library(SingleCellExperiment))
sce <- SingleCellExperiment(assays = list(counts = t(rd)),
                            colData = df)
reducedDim(sce, "Dim") <- rd
p <- plotReducedDim(sce, dimred = "Dim", colour_by = "cl")
p

Then, it is quite straightforward to add the curves. We just need to rename the components as X and Y

curves <- slingCurves(sds, as.df = TRUE) %>%
  dplyr::rename("X" = "Dim1", "Y" = "Dim2")
p + geom_path(data = curves %>% arrange(Order),
              aes(group = Lineage)) 

Similarly for the MST:

mst <- slingMST(sds, as.df = TRUE) %>%
  dplyr::rename("X" = "Dim1", "Y" = "Dim2")
p + geom_point(data = mst, size = 4) +
  geom_path(data = mst %>% arrange(Order), aes(group = Lineage), size = 2)

If you have trouble figuring out how to adapt this to other functions, feel free to open an issue on the traviz repo.

Session Info

sessionInfo()
## R version 4.3.1 (2023-06-16)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 22.04.3 LTS
## 
## Matrix products: default
## BLAS:   /home/biocbuild/bbs-3.18-bioc/R/lib/libRblas.so 
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0
## 
## 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       
## 
## time zone: America/New_York
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats4    stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] scater_1.30.0               scuttle_1.12.0             
##  [3] dplyr_1.1.3                 ggplot2_3.4.4              
##  [5] slingshot_2.10.0            TrajectoryUtils_1.10.0     
##  [7] SingleCellExperiment_1.24.0 SummarizedExperiment_1.32.0
##  [9] Biobase_2.62.0              GenomicRanges_1.54.0       
## [11] GenomeInfoDb_1.38.0         IRanges_2.36.0             
## [13] S4Vectors_0.40.0            BiocGenerics_0.48.0        
## [15] MatrixGenerics_1.14.0       matrixStats_1.0.0          
## [17] princurve_2.1.6             knitr_1.44                 
## 
## loaded via a namespace (and not attached):
##  [1] beeswarm_0.4.0            gtable_0.3.4             
##  [3] xfun_0.40                 bslib_0.5.1              
##  [5] ggrepel_0.9.4             lattice_0.22-5           
##  [7] vctrs_0.6.4               tools_4.3.1              
##  [9] bitops_1.0-7              generics_0.1.3           
## [11] parallel_4.3.1            tibble_3.2.1             
## [13] fansi_1.0.5               BiocNeighbors_1.20.0     
## [15] pkgconfig_2.0.3           Matrix_1.6-1.1           
## [17] sparseMatrixStats_1.14.0  lifecycle_1.0.3          
## [19] GenomeInfoDbData_1.2.11   compiler_4.3.1           
## [21] farver_2.1.1              munsell_0.5.0            
## [23] codetools_0.2-19          vipor_0.4.5              
## [25] htmltools_0.5.6.1         sass_0.4.7               
## [27] RCurl_1.98-1.12           yaml_2.3.7               
## [29] pillar_1.9.0              crayon_1.5.2             
## [31] jquerylib_0.1.4           BiocParallel_1.36.0      
## [33] DelayedArray_0.28.0       cachem_1.0.8             
## [35] viridis_0.6.4             abind_1.4-5              
## [37] rsvd_1.0.5                tidyselect_1.2.0         
## [39] digest_0.6.33             BiocSingular_1.18.0      
## [41] labeling_0.4.3            cowplot_1.1.1            
## [43] fastmap_1.1.1             grid_4.3.1               
## [45] colorspace_2.1-0          cli_3.6.1                
## [47] SparseArray_1.2.0         magrittr_2.0.3           
## [49] S4Arrays_1.2.0            utf8_1.2.4               
## [51] withr_2.5.1               DelayedMatrixStats_1.24.0
## [53] scales_1.2.1              ggbeeswarm_0.7.2         
## [55] rmarkdown_2.25            XVector_0.42.0           
## [57] igraph_1.5.1              gridExtra_2.3            
## [59] ScaledMatrix_1.10.0       beachmat_2.18.0          
## [61] evaluate_0.22             viridisLite_0.4.2        
## [63] irlba_2.3.5.1             rlang_1.1.1              
## [65] Rcpp_1.0.11               glue_1.6.2               
## [67] jsonlite_1.8.7            R6_2.5.1                 
## [69] zlibbioc_1.48.0

References

McCarthy, Davis J., Kieran R. Campbell, Aaron T. L. Lun, and Quin F. Willis. 2017. “Scater: Pre-Processing, Quality Control, Normalisation and Visualisation of Single-Cell RNA-Seq Data in R.” Bioinformatics 33 (8): 1179–86. https://doi.org/10.1093/bioinformatics/btw777.

Street, Kelly, Davide Risso, Russell B. Fletcher, Diya Das, John Ngai, Nir Yosef, Elizabeth Purdom, and Sandrine Dudoit. 2018. “Slingshot: cell lineage and pseudotime inference for single-cell transcriptomics.” BMC Genomics 19 (1): 477. https://doi.org/10.1186/s12864-018-4772-0.

Wickham, Hadley. 2016. Ggplot2: Elegant Graphics for Data Analysis. Springer-Verlag New York. https://ggplot2.tidyverse.org.