scGate to annotate integrated scRNA-seq datasets

A typical task in single-cell analysis is cell type annotation of datasets composed of multiple samples. You may have used one of several tools for batch-effect correction to integrate multiple samples, and generated a combined dataset. In this demo we will show how scGate can help you annotate an integrated dataset, by using simple, customizable models based on common marker genes from literature. We will show the case of a PBMC dataset integrated either with STACAS or Harmony, but the same applies to different integration tools.

Set up the environment

library(renv)
renv::restore()

library(ggplot2)
library(dplyr)
library(patchwork)
library(Seurat)
library(SeuratObject)
library(remotes)

if (!require("harmony", quietly = TRUE))
  install.packages("harmony")

#Packages from GitHub
if (!require("seurat-data", quietly = TRUE))
  remotes::install_github('satijalab/seurat-data')

if (!require("STACAS", quietly = TRUE))
  remotes::install_github("carmonalab/STACAS")

library(scGate)
library(SeuratData)
library(STACAS)

Get a test dataset

Download the dataset of PBMCs (SCP424) distributed with SeuratData. For more information on this dataset you can do ?pbmcsca

options(timeout = max(300, getOption("timeout")))

InstallData("pbmcsca")
data("pbmcsca")

scGate on STACAS-integrated object

Integrate different batches (in this example, datasets generated with different sequencing method) with STACAS

nfeatures <- 1000  # define number of variable features to consider
npcs <- 20  # define number of Principal Components for dimensionality reduction

pbmcsca <- UpdateSeuratObject(pbmcsca) |>
    NormalizeData()
pbmcsca.list <- SplitObject(pbmcsca, split.by = "Method")
pbmc.stacas <- Run.STACAS(pbmcsca.list, anchor.features = nfeatures, dims = 1:npcs)
pbmc.stacas <- RunUMAP(pbmc.stacas, dims = 1:npcs)
DimPlot(pbmc.stacas, group.by = "Method") + theme(aspect.ratio = 1)

We can run scGate directly on this integrated space, for instance to isolate NK cells

models.db <- scGate::get_scGateDB()
model.NK <- models.db$human$generic$NK

pbmc.stacas <- scGate(pbmc.stacas, model = model.NK, reduction = "pca", ncores = 4,
    output.col.name = "NK")

We can compare the automatic filtering to the “CellType” manual annotation by the authors:

DimPlot(pbmc.stacas, group.by = c("NK", "CellType"), ncol = 2) + theme(aspect.ratio = 1)

New models can be easily defined based on cell type-specific markers from literature. For instance, we can set up a new simple model to identify Megakaryocytes:

model.MK <- scGate::gating_model(name = "Megakaryocyte", signature = c("ITGA2B",
    "PF4", "PPBP"))

pbmc.stacas <- scGate(pbmc.stacas, model = model.MK, reduction = "pca", ncores = 4,
    output.col.name = "Megakaryocyte")
DimPlot(pbmc.stacas, group.by = c("Megakaryocyte", "CellType"), ncol = 2) + theme(aspect.ratio = 1)

We can also run multiple gating models at once. Besides pure/impure classifications for each model, scGate will also return a combined annotation based on all the models we provided. In this setting, scGate can be used as a multi-classifier to automatically annotate datasets:

models.hs <- models.db$human$generic
models.list <- models.hs[c("Bcell", "PlasmaCell", "CD4T", "CD8T", "Monocyte", "NK",
    "Erythrocyte", "Megakaryocyte", "Mast", "panDC")]

pbmc.stacas <- scGate(pbmc.stacas, model = models.list, reduction = "pca", ncores = 4)
DimPlot(pbmc.stacas, group.by = c("Method", "CellType", "scGate_multi"), ncol = 3) +
    theme(aspect.ratio = 1)

UCell scores for individual signatures are also available in metadata (’*_UCell’ columns). These scores are useful to see which features contribute more strongly to a particular gating model:

FeaturePlot(pbmc.stacas, ncol = 3, features = c("Tcell_UCell", "CD4T_UCell", "CD8T_UCell",
    "MoMacDC_UCell", "pDC_UCell", "Bcell_UCell"))

scGate on Harmony-integrated object

A very popular tool for single-cell data integration is Harmony. The RunHarmony() function provides a convenient wrapper to integrate samples stored in a Seurat object:

pbmcsca <- NormalizeData(pbmcsca) %>%
    FindVariableFeatures(nfeatures = nfeatures) %>%
    ScaleData() %>%
    RunPCA(npcs = npcs)
pbmc.harmony <- RunHarmony(pbmcsca, group.by.vars = "Method")

The corrected embeddings after batch effect correction will be stored in the ‘harmony’ reduction slot:

pbmc.harmony <- RunUMAP(pbmc.harmony, reduction = "harmony", dims = 1:npcs)

Let’s apply scGate in this space to isolate high-quality T cells:

models.db <- scGate::get_scGateDB()
model.Tcell <- models.db$human$generic$Tcell

pbmc.harmony <- scGate(pbmc.harmony, model = model.Tcell, reduction = "harmony",
    ncores = 4, output.col.name = "Tcell")
DimPlot(pbmc.harmony, group.by = c("Tcell", "CellType"), ncol = 2) + theme(aspect.ratio = 1)

We can also efficiently run multiple gating models at once, by providing a list of gating models:

models.db <- scGate::get_scGateDB()

models.hs <- models.db$human$generic
models.list <- models.hs[c("Bcell", "PlasmaCell", "CD4T", "CD8T", "Monocyte", "NK",
    "Erythrocyte", "Megakaryocyte", "Mast", "panDC")]

pbmc.harmony <- scGate(pbmc.harmony, model = models.list, reduction = "harmony",
    ncores = 4)
DimPlot(pbmc.harmony, group.by = c("Method", "CellType", "scGate_multi"), ncol = 3) +
    theme(aspect.ratio = 1)