Tutorial

Identifying Cell Types in Spatial Transcriptomics using Giotto

Difficulty: Advanced Time: 20 min read

Introduction

Single-cell RNA sequencing (scRNA-seq) tells us what genes are expressed in a cell, but spatial transcriptomics tells us where those cells are physically located in the tissue. This spatial context is vital for understanding tumor microenvironments and tissue architecture. In this tutorial, we will use the Giotto package in R to process spatial transcriptomics data, cluster cells, and map them back to their physical coordinates.

Architecture Overview


graph TD
    ExprMatrix(Gene Expression Matrix) --> GiottoObj[Create Giotto Object]
    Locs(Spatial Coordinates) --> GiottoObj
    
    GiottoObj --> Filter[Filter Low Quality Cells & Genes]
    Filter --> Norm[Normalize Expression Data]
    
    Norm --> PCA[Run PCA on Highly Variable Genes]
    Norm --> Network[Create Spatial Network: kNN]
    
    PCA --> Cluster(Leiden Clustering)
    Network --> Cluster
    
    Cluster --> UMAP[Visualize UMAP: Transcriptional Space]
    Cluster --> SpatialPlot[Visualize Spatial Plot: Physical Space]
    Cluster --> Markers[Identify Spatial Marker Genes: Gini/Scran]
        

Prerequisites

  • R (version 4.0+)
  • RStudio (recommended)
  • Python (Giotto uses reticulate to call Python libraries like pandas and scikit-learn under the hood)
  • A spatial transcriptomics dataset (e.g., Visium)

Step 1: Install Giotto

Giotto requires setting up a Python environment within R to access specific modules.

# Install Giotto from GitHub
if (!requireNamespace("remotes", quietly = TRUE)) {
  install.packages("remotes")
}
remotes::install_github("RubD/Giotto")

library(Giotto)

# Install the Giotto Python environment
installGiottoEnvironment()

Step 2: Create the Giotto Object

A Giotto object holds the gene expression matrix, the spatial coordinates of the spots/cells, and optional image data.

# Assuming you have the expression matrix and spatial coordinates
# expression_matrix: rows = genes, columns = spots/cells
# spatial_locations: rows = spots/cells, columns = X, Y

my_giotto_object = createGiottoObject(raw_exprs = expression_matrix, 
                                      spatial_locs = spatial_locations)

# Filter out low-quality cells and genes
my_giotto_object = filterGiotto(gobject = my_giotto_object, 
                                expression_threshold = 1, 
                                gene_det_in_min_cells = 10, 
                                min_det_genes_per_cell = 200)

# Normalize the data
my_giotto_object = normalizeGiotto(gobject = my_giotto_object)

Step 3: Dimensionality Reduction and Clustering

We identify highly variable genes, run PCA, build a spatial network, and then cluster the cells to identify putative cell types.

# Identify highly variable genes
my_giotto_object = calculateHVG(gobject = my_giotto_object)

# Run PCA
my_giotto_object = runPCA(gobject = my_giotto_object)

# Run UMAP for visualization in expression space
my_giotto_object = runUMAP(my_giotto_object, dimensions_to_use = 1:10)

# Create a Spatial Network (connects neighboring cells in physical space)
my_giotto_object = createSpatialNetwork(gobject = my_giotto_object, method = 'kNN', k = 5)

# Cluster the cells using Leiden community detection
my_giotto_object = createNearestNetwork(gobject = my_giotto_object, dimensions_to_use = 1:10, k = 15)
my_giotto_object = doLeidenCluster(gobject = my_giotto_object, resolution = 0.4, name = 'leiden_clus')

Step 4: Spatial Visualization and Marker Gene Identification

The true power of Giotto is visualizing these transcriptional clusters mapped back onto the original tissue slice. Once we see a spatial pattern (e.g., a tumor border), we can identify which genes are driving that spatial domain.

# Plot UMAP space (Transcriptional similarity)
plotUMAP(gobject = my_giotto_object, cell_color = 'leiden_clus', show_NN_network = F, point_size = 2.5)

# Plot Spatial space (Physical location in the tissue)
spatPlot(gobject = my_giotto_object, cell_color = 'leiden_clus', point_size = 3)

# Identify Marker Genes for each cluster using Gini
markers = findMarkers_one_vs_all(gobject = my_giotto_object, 
                                 method = 'gini', 
                                 expression_values = 'normalized', 
                                 cluster_column = 'leiden_clus', 
                                 min_genes = 20)

# Visualize expression of a top marker gene in physical space
top_gene = markers$genes[1]
spatGenePlot(gobject = my_giotto_object, expression_values = 'scaled', genes = top_gene)

Conclusion

Giotto provides an incredibly comprehensive suite of tools for spatial transcriptomics. By clustering cells based on their gene expression and then mapping those clusters back to physical tissue coordinates, researchers can explicitly study how cell types interact in their native environment, identify novel spatially-restricted cell populations, and pinpoint the exact biomarker genes driving tissue organization. This is a foundational leap beyond traditional, dissociated single-cell sequencing.