Skip to contents

Overview

SpaGER provides seamless integration with Seurat (v4 and v5), the most widely used R package for single-cell analysis. This vignette demonstrates how to use SpaGER with Seurat objects.

Prerequisites

library(SpaGER)

# Check Seurat availability
if (requireNamespace("Seurat", quietly = TRUE)) {
  check_seurat_version()
} else {
  message("Seurat not installed. Code examples shown but not executed.")
}

Basic Workflow with Seurat

Load Your Data

library(Seurat)

# Load your spatial and scRNA-seq Seurat objects
# Example: Visium + scRNA-seq reference
spatial_obj <- readRDS("path/to/spatial_seurat.rds")
scrna_obj <- readRDS("path/to/scrna_seurat.rds")

# Check objects
spatial_obj
scrna_obj

Prepare Data (Optional)

# Ensure data is normalized
spatial_obj <- prepare_seurat(spatial_obj, normalize = TRUE)
scrna_obj <- prepare_seurat(scrna_obj, normalize = TRUE)

Run SpaGE

# Predict unmeasured genes
spatial_obj <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  n_pv = 30,
  n_neighbors = 50,
  assay_name = "SpaGE",  # Name for new assay
  verbose = TRUE
)

# Check the new assay was added
Assays(spatial_obj)

Access Predictions

# Switch to SpaGE assay
DefaultAssay(spatial_obj) <- "SpaGE"

# Get predicted expression matrix
predicted_expr <- GetAssayData(spatial_obj, slot = "data")
dim(predicted_expr)

# View specific genes
head(predicted_expr[c("Gad1", "Slc17a7", "Mbp"), ])

Seurat v4 vs v5

SpaGER automatically detects your Seurat version and uses the appropriate interface:

Feature Seurat v4 Seurat v5
Data access slot parameter layer parameter
Default slot/layer “data” “data”
Assay creation CreateAssayObject() CreateAssay5Object()

Explicit Version Control

# For Seurat v4 (explicit)
spatial_obj <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  slot = "data",        # v4 style
  n_pv = 30
)

# For Seurat v5 (explicit)
spatial_obj <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  layer = "data",       # v5 style
  n_pv = 30
)

Predict Specific Genes

# Define genes of interest
marker_genes <- c(
  "Gad1", "Gad2",           # GABAergic markers
  "Slc17a7", "Slc17a6",     # Glutamatergic markers
  "Mbp", "Plp1",            # Oligodendrocyte markers
  "Aqp4", "Gfap"            # Astrocyte markers
)

# Predict only these genes
spatial_obj <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  genes_to_predict = marker_genes,
  n_pv = 30,
  assay_name = "SpaGE_markers"
)

Return Data Frame Instead

# Don't add to Seurat object, return data frame
predicted_df <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  n_pv = 30,
  add_to_object = FALSE  # Return data frame
)

class(predicted_df)
dim(predicted_df)

Working with Different Assays

# Specify which assay to use from each object
spatial_obj <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  assay_spatial = "Spatial",  # Use Spatial assay
  assay_rna = "RNA",          # Use RNA assay
  n_pv = 30
)

Visualization After Prediction

# Set to predicted assay
DefaultAssay(spatial_obj) <- "SpaGE"

# Spatial feature plot
SpatialFeaturePlot(spatial_obj, features = "Gad1")

# Expression heatmap
DoHeatmap(spatial_obj, features = marker_genes)

# Violin plot
VlnPlot(spatial_obj, features = "Gad1", group.by = "seurat_clusters")

Batch Processing Multiple Gene Sets

# Define gene sets
gene_sets <- list(
  excitatory = c("Slc17a7", "Slc17a6", "Camk2a"),
  inhibitory = c("Gad1", "Gad2", "Slc32a1"),
  glial = c("Mbp", "Gfap", "Aqp4", "Cx3cr1")
)

# Predict all gene sets
# Note: For Seurat objects, process one set at a time
for (set_name in names(gene_sets)) {
  assay_name <- paste0("SpaGE_", set_name)
  spatial_obj <- SpaGE.Seurat(
    spatial_seurat = spatial_obj,
    rna_seurat = scrna_obj,
    genes_to_predict = gene_sets[[set_name]],
    n_pv = 30,
    assay_name = assay_name,
    verbose = FALSE
  )
}

Assays(spatial_obj)

Tips for Best Results

1. Matching Cell Types

Ensure your scRNA-seq reference contains cell types present in your spatial data:

# Check cell type composition
table(scrna_obj$cell_type)

# Optionally subset to relevant cell types
scrna_subset <- subset(scrna_obj, cell_type %in% c("Neuron", "Astrocyte", "Oligodendrocyte"))

2. Gene Filtering

# Filter lowly expressed genes before SpaGE
scrna_obj <- scrna_obj[rowSums(GetAssayData(scrna_obj) > 0) > 50, ]

3. Normalize Consistently

# Use same normalization for both datasets
spatial_obj <- NormalizeData(spatial_obj, normalization.method = "LogNormalize")
scrna_obj <- NormalizeData(scrna_obj, normalization.method = "LogNormalize")

Complete Example Workflow

# 1. Load data
spatial_obj <- LoadSeuratRds("spatial.rds")
scrna_obj <- LoadSeuratRds("scrna.rds")

# 2. Prepare (normalize if needed)
spatial_obj <- prepare_seurat(spatial_obj)
scrna_obj <- prepare_seurat(scrna_obj)

# 3. Define genes to predict
genes <- setdiff(rownames(scrna_obj), rownames(spatial_obj))

# 4. Run SpaGE
spatial_obj <- SpaGE.Seurat(
  spatial_seurat = spatial_obj,
  rna_seurat = scrna_obj,
  genes_to_predict = genes[1:100],  # First 100 unmeasured genes
  n_pv = 30,
  n_neighbors = 50
)

# 5. Visualize
DefaultAssay(spatial_obj) <- "SpaGE"
SpatialFeaturePlot(spatial_obj, features = genes[1:4])

# 6. Save
saveRDS(spatial_obj, "spatial_with_predictions.rds")

Troubleshooting

Common Issues

  1. “No shared genes”: Ensure gene names match between datasets

    # Check gene name overlap
    shared <- intersect(rownames(spatial_obj), rownames(scrna_obj))
    length(shared)
  2. Memory issues: For large datasets, predict genes in batches

    # Split genes into batches
    all_genes <- setdiff(rownames(scrna_obj), rownames(spatial_obj))
    batches <- split(all_genes, ceiling(seq_along(all_genes) / 100))
  3. Slow performance: Reduce n_pv or n_neighbors

    # Faster but potentially less accurate
    spatial_obj <- SpaGE.Seurat(spatial_obj, scrna_obj, n_pv = 20, n_neighbors = 30)

Session Information

sessionInfo()
#> R version 4.4.0 (2024-04-24)
#> Platform: aarch64-apple-darwin20
#> Running under: macOS 15.6.1
#> 
#> 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] C
#> 
#> time zone: Asia/Shanghai
#> tzcode source: internal
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] SpaGER_1.0.0
#> 
#> loaded via a namespace (and not attached):
#>   [1] deldir_2.0-4           pbapply_1.7-4          gridExtra_2.3         
#>   [4] rlang_1.1.7            magrittr_2.0.4         RcppAnnoy_0.0.23      
#>   [7] otel_0.2.0             spatstat.geom_3.7-0    matrixStats_1.5.0     
#>  [10] ggridges_0.5.7         compiler_4.4.0         png_0.1-8             
#>  [13] systemfonts_1.3.1      vctrs_0.7.1            reshape2_1.4.5        
#>  [16] stringr_1.6.0          pkgconfig_2.0.3        fastmap_1.2.0         
#>  [19] promises_1.5.0         rmarkdown_2.30         ragg_1.5.0            
#>  [22] purrr_1.2.1            xfun_0.56              cachem_1.1.0          
#>  [25] jsonlite_2.0.0         goftest_1.2-3          later_1.4.5           
#>  [28] spatstat.utils_3.2-1   irlba_2.3.5.1          parallel_4.4.0        
#>  [31] cluster_2.1.8.1        R6_2.6.1               ica_1.0-3             
#>  [34] spatstat.data_3.1-9    bslib_0.9.0            stringi_1.8.7         
#>  [37] RColorBrewer_1.1-3     reticulate_1.44.1      spatstat.univar_3.1-6 
#>  [40] parallelly_1.46.1      lmtest_0.9-40          jquerylib_0.1.4       
#>  [43] scattermore_1.2        Rcpp_1.1.1             knitr_1.51            
#>  [46] tensor_1.5.1           future.apply_1.20.1    zoo_1.8-15            
#>  [49] sctransform_0.4.3      FNN_1.1.4.1            httpuv_1.6.16         
#>  [52] Matrix_1.7-4           splines_4.4.0          igraph_2.2.1          
#>  [55] tidyselect_1.2.1       abind_1.4-8            dichromat_2.0-0.1     
#>  [58] yaml_2.3.12            spatstat.random_3.4-4  spatstat.explore_3.7-0
#>  [61] codetools_0.2-20       miniUI_0.1.2           listenv_0.10.0        
#>  [64] plyr_1.8.9             lattice_0.22-7         tibble_3.3.1          
#>  [67] shiny_1.12.1           S7_0.2.1               ROCR_1.0-12           
#>  [70] evaluate_1.0.5         Rtsne_0.17             future_1.69.0         
#>  [73] desc_1.4.3             survival_3.8-3         polyclip_1.10-7       
#>  [76] fitdistrplus_1.2-5     pillar_1.11.1          Seurat_4.4.0          
#>  [79] KernSmooth_2.23-26     plotly_4.11.0          generics_0.1.4        
#>  [82] sp_2.2-0               ggplot2_4.0.1          scales_1.4.0          
#>  [85] globals_0.18.0         xtable_1.8-4           glue_1.8.0            
#>  [88] lazyeval_0.2.2         tools_4.4.0            data.table_1.18.0     
#>  [91] RANN_2.6.2             dotCall64_1.2          fs_1.6.6              
#>  [94] leiden_0.4.3.1         cowplot_1.2.0          grid_4.4.0            
#>  [97] tidyr_1.3.2            nlme_3.1-168           patchwork_1.3.2       
#> [100] cli_3.6.5              spatstat.sparse_3.1-0  textshaping_1.0.4     
#> [103] spam_2.11-3            viridisLite_0.4.2      dplyr_1.1.4           
#> [106] uwot_0.2.4             gtable_0.3.6           sass_0.4.10           
#> [109] digest_0.6.39          progressr_0.18.0       ggrepel_0.9.6         
#> [112] htmlwidgets_1.6.4      SeuratObject_4.1.4     farver_2.1.2          
#> [115] htmltools_0.5.9        pkgdown_2.1.3          lifecycle_1.0.5       
#> [118] httr_1.4.7             mime_0.13              MASS_7.3-65