To begin with the analysis, we will first load the required packages. The downstream analysis of the scRNA-seq is built upon Seurat and sctransform packages. The scDblFinder package is used for identifying and removing doublets in the dataset. The single-cell annotation is carried out using the marker-based scSorter method.
library("Seurat")
library("ggplot2")
library("sctransform")
library("BiocParallel")
library("scDblFinder")
library("SingleCellExperiment")
library("cowplot")
theme_set(theme_cowplot())
library("RColorBrewer")
library("viridis")
library("scSorter")
library("knitr")
library("viridisLite")
library("patchwork")
library("tidyverse")
library("dplyr")
library("Matrix")
First, we will load the filtered count matrix from cellranger. This matrix contains the scRNA-seq counts from all the HPAP samples.
panc_data <- Read10X(data.dir = "./data/HPAP_samples_aggr_18Apr2022/outs/count/filtered_feature_bc_matrix/")
The dimension of the raw counts matrix after merging all HPAP scRNA-seq samples with cellranger is shown below. There are total of 36601 genes and 269417 cells.
# panc_data <- Read10X(data.dir = "PATH_TO_FEATURE_MATRIX")
dim(panc_data)
## [1] 36601 269417
The Seurat object initialization step above only considered cells that expressed at least 200 genes. The min.cells- parameter will include features detected in at least three cells. The min.features - Include cells where at least three fifty features are detected.
With the above parameters the count matrix will also be subsetted. Optionally, to revive the excluded features, create a new object with a lower threshold.
panc <- CreateSeuratObject(counts = panc_data, min.cells = 3, min.features = 200,
project = "hpap@67")
dim(panc)
## [1] 32066 258379
In the Seurat object, 32066 genes and 258379 cells were present after passing the thresholds.
Here, we will add four new columns to the Seurat metadata. The first column sample_id contains raw sample names from cellranger, hpap_id refers to the donor identifier, the disease_id corresponds to the numeric count in each disease type, and finally the disease_state shows the general state of disease (CTL, AAB, and T1D).
## Add metadata information
sample <- read.csv(file.path("./metadata", "HPAP_samples_aggr_18Apr2022_cellranger.csv"), stringsAsFactors=F)
Parse through the sample ids, disease states, and donor ids. Extract the information and add information to metadata
sample_id <- sample$sample_id
disease_state <- sample$DiseaseState
sample$disease_state <- sample$DiseaseState
hpap_id <- sub("_.*", "", sample$sample_id)
sample$DiseaseState[sample$DiseaseState=="T1D"] = c(paste("T1D_",seq(1:length(sample$DiseaseState[sample$DiseaseState=="T1D"]))))
sample$DiseaseState[sample$DiseaseState=="T2D"] = c(paste("T2D_",seq(1:length(sample$DiseaseState[sample$DiseaseState=="T2D"]))))
sample$DiseaseState[sample$DiseaseState=="Control"] = c(paste("Control_",seq(1:length(sample$DiseaseState[sample$DiseaseState=="Control"]))))
sample$DiseaseState[sample$DiseaseState=="AAB"] = c(paste("AAB_",seq(1:length(sample$DiseaseState[sample$DiseaseState=="AAB"]))))
sample_disease <- sample$DiseaseState
colnames(sample)[4]="sample_disease"
write.csv(sample, "./metadata/HPAP_samples_aggr_18Apr2022_seurat.csv", row.names = F)
## Extract Patient ID
id <- as.numeric(gsub(".*(\\b\\d+\\b).*", "\\1", rownames(panc@meta.data)))
df <- data.frame(id)
df$sample_id <- sample_id[df$id]
df$hpap_id <- hpap_id[df$id]
df$disease_state <- disease_state[df$id]
df$disease_id <- sample_disease[df$id]
Adding donor ids, sample_ids, and disease state columns to metadata.
## Add Patient info to object
CellsMeta = panc@meta.data
## Add sample_id
CellsMeta["sample_id"] <- df$sample_id
CellsMetaTrim <- subset(CellsMeta, select = c("sample_id"))
panc <- AddMetaData(panc, CellsMetaTrim)
## Add hpap_id
CellsMeta["hpap_id"] <- df$hpap_id
CellsMetaTrim <- subset(CellsMeta, select = c("hpap_id"))
panc <- AddMetaData(panc, CellsMetaTrim)
## Add disease_id
CellsMeta["disease_id"] <- df$disease_id
CellsMetaTrim <- subset(CellsMeta, select = c("disease_id"))
panc <- AddMetaData(panc, CellsMetaTrim)
## Add disease_state
CellsMeta["disease_state"] <- df$disease_state
CellsMetaTrim <- subset(CellsMeta, select = c("disease_state"))
panc <- AddMetaData(panc, CellsMetaTrim)
head(panc@meta.data) %>%
kable(format = "html", col.names = colnames(head(panc@meta.data))) %>%
kable_styling() %>%
kableExtra::scroll_box(width = "100%", height = "300px")
orig.ident | nCount_RNA | nFeature_RNA | sample_id | hpap_id | disease_id | disease_state | |
---|---|---|---|---|---|---|---|
AAACCTGAGCGTTGCC-1 | hpap@67 | 16875 | 4080 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D |
AAACCTGAGGACAGAA-1 | hpap@67 | 6497 | 892 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D |
AAACCTGAGTCGTACT-1 | hpap@67 | 1169 | 253 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D |
AAACCTGCAACTGCTA-1 | hpap@67 | 13689 | 3553 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D |
AAACCTGCAATGTAAG-1 | hpap@67 | 16375 | 3583 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D |
AAACCTGCACCAGGTC-1 | hpap@67 | 16431 | 3438 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D |
## Calculate MT %
panc[["percent.mt"]] <- PercentageFeatureSet(panc, pattern = "^MT-")
The below violin plots shows the number of features, counts, and mitochondrial reads after intial pre-processing
Violin plots showing nFeature_RNA, nCount_RNA, and percent.mt with points.
VlnPlot(panc, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3, group.by = "disease_state",
pt.size = 0.001, combine = T) & theme(legend.position = 'none',
axis.title.x = element_blank())
Violin plots showing nFeature_RNA, nCount_RNA, and percent.mt without points.
VlnPlot(panc, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3, group.by = "disease_state",
pt.size = 0, combine = T) & theme(legend.position = 'none',
axis.title.x = element_blank())
The FeatureScatter plots used to visualize feature-feature relationships. Correlation between nCount_RNA - nFeature_RNA after initial pre-processing is measured.
# FeatureScatter used to visualize feature-feature relationships.
FeatureScatter(panc, feature1 = "nCount_RNA", feature2 = "percent.mt", group.by = "disease_state")
Correlation between nCount_RNA - percent.mt after initial pre-processing is shown below.
FeatureScatter(panc, feature1 = "nCount_RNA", feature2 = "nFeature_RNA", group.by = "disease_state")
We measure the distribution of cells across different individuals such as healthy, AAB, T1D, and T2D after initial pre-processing.
# Create Data
## All- AAB Control T1D T2D
Prop <- c(table(panc$disease_state)[[1]],
table(panc$disease_state)[[2]] ,
table(panc$disease_state)[[3]],
table(panc$disease_state)[[4]])
# number of colors in the palette
no_of_colors <- length(Prop)
# options represent the color types, there are altogether 8 options.
palette <- viridis_pal(option = "D")(no_of_colors)
# hex color codes
palette
## [1] "#440154FF" "#31688EFF" "#35B779FF" "#FDE725FF"
Pie chart showing the overall number of donors and the aggregated count of cells present in each disease group.
# represents colors in a pie chart manner
pie(Prop, labels = c(paste0("AAB \n ncells= ", Prop[1], "\n ndonors= 10"),
paste0("CTL \n ncells= ", Prop[2], "\n ndonors= 31"),
paste0("\n T1D \n ncells= ", Prop[3], "\n ndonors= 9"),
paste0("\n T2D \n ncells= ", Prop[4], "\n ndonors= 17")),
col = palette)
Calculate the total number of cells present in individual donors across all 4 disease groups. The results are stored in data frames.
## For different groups
## all cells
bf_all <- table(panc$disease_id)
## aab cells
bf_aab <- bf_all[grep("AAB", names(bf_all))]
names(bf_aab) <- gsub("_ ", "", names(bf_aab))
bf_aab <- as.data.frame(bf_aab)
## ctl cells
bf_ctl <- bf_all[grep("Control", names(bf_all))]
names(bf_ctl) <- gsub("_ ", "", names(bf_ctl))
bf_ctl <- as.data.frame(bf_ctl)
bf_ctl$Var1 <- gsub("Control", "CTL", bf_ctl$Var1)
## t1d cells
bf_t1d <- bf_all[grep("T1D", names(bf_all))]
names(bf_t1d) <- gsub("_ ", "", names(bf_t1d))
bf_t1d <- as.data.frame(bf_t1d)
## t2d cells
bf_t2d <- bf_all[grep("T2D", names(bf_all))]
names(bf_t2d) <- gsub("_ ", "", names(bf_t2d))
bf_t2d <- as.data.frame(bf_t2d)
Pie chart showing the cell distribution in each AAB donor
## AAB
pie_labels <- paste0(bf_aab$Var1, " ", round(100 * bf_aab$Freq/sum(bf_aab$Freq), 2), "%")
pie(bf_aab$Freq, labels = pie_labels, col = hcl.colors(length(bf_aab$Var1), "Purples"))
Pie chart showing the cell distribution in each healthy donor
## CTL
pie_labels <- paste0(bf_ctl$Var1, " ", round(100 * bf_ctl$Freq/sum(bf_ctl$Freq), 2), "%")
pie(bf_ctl$Freq, labels = pie_labels, col = hcl.colors(length(bf_ctl$Var1), "TealGrn"))
Pie chart showing the cell distribution in each T1D and T2D donors
## T1D
pie_labels <- paste0(bf_t1d$Var1, " ", round(100 * bf_t1d$Freq/sum(bf_t1d$Freq), 2), "%")
pie(bf_t1d$Freq, labels = pie_labels, col = hcl.colors(length(bf_ctl$Var1), "Green-Yellow"))
## T2D
pie_labels <- paste0(bf_t2d$Var1, " ", round(100 * bf_t2d$Freq/sum(bf_t2d$Freq), 2), "%")
pie(bf_t2d$Freq, labels = pie_labels, col = c("#FFEA00", "#FCF55F", "#FADA5E",
"#FAFA33", "#F4BB44", "#FBEC5D",
"#FFFF00", "#FFFAA0", "#FFE5B4"))
Median gene number showing the cell distribution across all groups after initial pre-processing
## Median Gene Per Sample
df_mgps <- data.frame(panc@meta.data$nFeature_RNA, panc@meta.data$disease_state)
colnames(df_mgps) <- c("Median_Gene_Number", "Condition")
ggplot(df_mgps, aes(Condition, Median_Gene_Number)) + geom_boxplot(aes(fill = Condition),
width=0.5, outlier.size = 0.2) +
scale_fill_viridis(discrete = TRUE) + xlab("") + theme(legend.position = "none")
The scDblFinder function is employed to remove the potential doublets from each HPAP donor separately. The parameter sample_id refers to individual donor. The function uses an object from SingleCellExperiment class, therefore the SingleCellExperiment package is used for conversion.
## Convert object into singlecellexperiment
panc.sce <- as.SingleCellExperiment(panc)
panc.sce <- scDblFinder(panc.sce, samples="sample_id", clusters=FALSE, BPPARAM=MulticoreParam(10))
## Convert sce object back to seurat
panc_seurat <- as.Seurat(panc.sce, counts = "counts", data = "logcounts")
table(panc.sce$scDblFinder.class)
##
## singlet doublet
## 234285 24094
The doublet information is stored in the metadata. The updated metadata can be found below
head(panc@meta.data) %>%
kable(format = "html", col.names = colnames(head(panc@meta.data))) %>%
kable_styling() %>%
kableExtra::scroll_box(width = "100%", height = "300px")
orig.ident | nCount_RNA | nFeature_RNA | sample_id | hpap_id | disease_id | disease_state | percent.mt | |
---|---|---|---|---|---|---|---|---|
AAACCTGAGCGTTGCC-1 | hpap@67 | 16875 | 4080 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D | 7.330370 |
AAACCTGAGGACAGAA-1 | hpap@67 | 6497 | 892 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D | 1.062029 |
AAACCTGAGTCGTACT-1 | hpap@67 | 1169 | 253 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D | 4.362703 |
AAACCTGCAACTGCTA-1 | hpap@67 | 13689 | 3553 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D | 3.382278 |
AAACCTGCAATGTAAG-1 | hpap@67 | 16375 | 3583 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D | 3.877863 |
AAACCTGCACCAGGTC-1 | hpap@67 | 16431 | 3438 | HPAP021_75162_T1DIslets | HPAP021 | T1D_ 1 | T1D | 1.545858 |
The nFeature_RNA and nCount_RNA represents the number of genes detected in each cell and the total number of molecules (UMIs) detected within a cell respectively. While the low nFeature_RNA in a cell mean that it may be dead/dying or it may represent an empty droplet, the high nCount_RNA and nFeature_RNA denotes that the cell may be a doublet or multiplet. This filtering along with mitochondrial reads is crucial pre-processing step, because, removing such outliers from these groups might also remove some of the doublets or dead/empty droplets.
The cell being either doublet or singlet is stored in column scDlFinder.class. The potential doublets are removed in this step.
# After doublet removal
panc <- subset(panc_seurat, subset = scDblFinder.class == "singlet")
The final data after removing potential doublets and subsetting based on nFeature and percent.mt is shown below
panc_new <- subset(panc, subset = nFeature_RNA > 200 & nFeature_RNA < 9000
& percent.mt < 25
& nCount_RNA < 100000
)
dim(panc_new)
## [1] 32066 222077
After removing doublets, now we can proceed with further pre-processing steps. For ex, Mitochondrial genes are useful indicators of cell state.
Adding the Mitochondrial genes to the metadata after pre-processing
panc[["percent.mt"]] <- PercentageFeatureSet(panc, pattern = "^MT-")
The metadata information is updated after final pre-processing. The violin plot are used to show the number of features, counts, and the percentage of mitochondrial reads after all the pre-processing.
Violin plots showing nFeature_RNA, nCount_RNA, and percent.mt with points.
VlnPlot(panc_new, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3, group.by = "disease_state",
pt.size = 0.001, combine = T) & theme(legend.position = 'none',
axis.title.x = element_blank())
Violin plots showing nFeature_RNA, nCount_RNA, and percent.mt without points.
VlnPlot(panc_new, features = c("nFeature_RNA", "nCount_RNA", "percent.mt"), ncol = 3, group.by = "disease_state",
pt.size = 0, combine = T) & theme(legend.position = 'none',
axis.title.x = element_blank())
Correlation between nCount_RNA - nFeature_RNA after filtering. The FeatureScatter is typically used to visualize feature-feature relationships.
FeatureScatter(panc_new, feature1 = "nCount_RNA", feature2 = "percent.mt", group.by = "disease_state")
Correlation between nCount_RNA - percent.mt after filtering.
FeatureScatter(panc_new, feature1 = "nCount_RNA", feature2 = "nFeature_RNA", group.by = "disease_state")
We measure the distribution of cells across different individuals such as healthy, AAB, T1D, and T2D after initial pre-processing.
# Create Data
## AAB Control T1D T2D
Prop <- c(table(panc_new$disease_state)[[1]], table(panc_new$disease_state)[[2]] , table(panc_new$disease_state)[[3]], table(panc_new$disease_state)[[4]])
# number of colors in the palette
no_of_colors <- length(Prop)
# options represent the color types, there are altogether 8 options.
palette <- viridis_pal(option = "D")(no_of_colors)
# hex color codes
palette
## [1] "#440154FF" "#31688EFF" "#35B779FF" "#FDE725FF"
Pie chart showing the overall number of donors and the aggregated count of cells present in each disease group.
# represents colors in a pie chart manner
pie(Prop, labels = c(paste0("AAB \n ncells= ", Prop[1], "\n ndonors= 10"),
paste0("CTL \n ncells= ", Prop[2], "\n ndonors= 31"),
paste0("\n T1D \n ncells= ", Prop[3], "\n ndonors= 9"),
paste0("\n T2D \n ncells= ", Prop[4], "\n ndonors= 17")),
col = palette)
Calculate the total number of cells present in individual donors across all 4 disease groups. The results are stored in data frames.
## Metrics for all samples
## all cells
bf_all <- table(panc_new$disease_id)
## aab cells
bf_aab <- bf_all[grep("AAB", names(bf_all))]
names(bf_aab) <- gsub("_ ", "", names(bf_aab))
bf_aab <- as.data.frame(bf_aab)
## ctl cells
bf_ctl <- bf_all[grep("Control", names(bf_all))]
names(bf_ctl) <- gsub("_ ", "", names(bf_ctl))
bf_ctl <- as.data.frame(bf_ctl)
bf_ctl$Var1 <- gsub("Control", "CTL", bf_ctl$Var1)
## t1d cells
bf_t1d <- bf_all[grep("T1D", names(bf_all))]
names(bf_t1d) <- gsub("_ ", "", names(bf_t1d))
bf_t1d <- as.data.frame(bf_t1d)
## t2d cells
bf_t2d <- bf_all[grep("T2D", names(bf_all))]
names(bf_t2d) <- gsub("_ ", "", names(bf_t2d))
bf_t2d <- as.data.frame(bf_t2d)
Pie chart showing the cell distribution in each AAB donor after pre-processing
## AAB
pie_labels <- paste0(bf_aab$Var1, " ", round(100 * bf_aab$Freq/sum(bf_aab$Freq), 2), "%")
pie(bf_aab$Freq, labels = pie_labels, col = hcl.colors(length(bf_aab$Var1), "Purples"))
Pie chart showing the cell distribution in each healthy donor after pre-processing
## CTL
pie_labels <- paste0(bf_ctl$Var1, " ", round(100 * bf_ctl$Freq/sum(bf_ctl$Freq), 2), "%")
pie(bf_ctl$Freq, labels = pie_labels, col = hcl.colors(length(bf_ctl$Var1), "TealGrn"))
Pie chart showing the cell distribution in each T1D and T2D donors after pre-processing
## T1D
pie_labels <- paste0(bf_t1d$Var1, " ", round(100 * bf_t1d$Freq/sum(bf_t1d$Freq), 2), "%")
pie(bf_t1d$Freq, labels = pie_labels, col = hcl.colors(length(bf_ctl$Var1), "Green-Yellow"))
## T2D
pie_labels <- paste0(bf_t2d$Var1, " ", round(100 * bf_t2d$Freq/sum(bf_t2d$Freq), 2), "%")
pie(bf_t2d$Freq, labels = pie_labels, col = c("#FFEA00", "#FCF55F", "#FADA5E",
"#FAFA33", "#F4BB44", "#FBEC5D",
"#FFFF00", "#FFFAA0", "#FFE5B4"))
Median gene number showing the cell distribution across all groups after final pre-processing
## Median Gene Per Sample after filtering
df_mgps <- data.frame(panc_new@meta.data$nFeature_RNA, panc_new@meta.data$disease_state)
colnames(df_mgps) <- c("Median_Gene_Number", "Condition")
ggplot(df_mgps, aes(Condition, Median_Gene_Number)) + geom_boxplot(aes(fill = Condition),
width=0.5, outlier.size = 0.2) +
scale_fill_viridis(discrete = TRUE) + xlab("") + theme(legend.position = "none")
The seurat’s SCTranform (SCT) function is used to normalize the counts that measures the differences in sequencing depth per cell for each sample. The SCT method is built on the concept regularized negative binomial model to perform normalization and variance stabilization of single-cell RNA-seq data. It removes the variation due to sequencing depth (nUMIs). The vars.to.regress parameter allows us to regress out the variation from other sources such as percentage of mitochondrial. The output of SCT model is the normalized expression levels for all the transcripts. Lastly, the variable.features.n parameter is used to select the variable features and is set as 3000.
panc_new_sct <- SCTransform(panc_new, method = "glmGamPoi", variable.features.n = 3000, vars.to.regress = "percent.mt", verbose = FALSE)
The seurat object now consists of two assays RNA and SCT, with the default being set as SCT.
DefaultAssay(panc_new_sct)
## [1] "SCT"
These are now standard steps in the Seurat workflow for visualization and clustering
panc_new_sct <- RunPCA(panc_new_sct, verbose = TRUE)
Plot showing heatmaps of PCs- 1 to 12 from the PCA analysis
DimHeatmap(panc_new_sct, dims = 1:12, cells = 500, balanced = TRUE)
Plot showing heatmaps of PCs- 13 to 24 from the PCA analysis
DimHeatmap(panc_new_sct, dims = 13:24, cells = 500, balanced = TRUE)
Plot showing heatmaps of PCs- 25 to 36 from the PCA analysis
DimHeatmap(panc_new_sct, dims = 25:36, cells = 500, balanced = TRUE)
Plot showing the variance explained by PCs from the PCA analysis
ElbowPlot(panc_new_sct, ndims = 40)
ElbowPlot(panc_new_sct)
The Uniform Manifold Approximation and Projection (UMAP) dimensional reduction technique is run on the first 20 principal components.
panc_new_sct <- RunUMAP(panc_new_sct, dims = 1:20, verbose = FALSE)
Here we compute the k nearest neighbors in the dataset. The nearest neighbors are calculated on the reduced dimensions from the PCA. We use first 20 principal components.
panc_new_sct <- FindNeighbors(panc_new_sct, dims = 1:20, verbose = FALSE)
Once we have calculated the k-nearest neighbors in previous step, we will find the clusters of cells by the shared nearest neihbor (SNN) clustering algorithm. Here, we have set the resolution as 0.8. The higher resolution usually gives more number of clusters.
panc_new_sct <- FindClusters(panc_new_sct, resolution = 0.8, method = "igraph", verbose = FALSE)
UMAP plot showing the clusters based on SCT data and snn optimization at resolution 0.8
DimPlot(panc_new_sct, group.by='SCT_snn_res.0.8', reduction='umap') +
ggtitle('SCT_snn_res.0.8')
UMAP plot showing the distribution of cells across different disease types.
DimPlot(panc_new_sct, group.by='disease_state', reduction='umap') +
ggtitle('Disease type')
UMAP plot showing the cell distribution with respect to individual donors
DimPlot(panc_new_sct, group.by='hpap_id', reduction='umap') +
ggtitle('Sample type')
Loading marker genes data
anno <- read.csv("./annot/anno.csv")
anno[,1] <- NULL
We used marker-based scSorter cell annotation method for assigning cells to known cell type based on the marker genes. The markers for each cell type were added based on comprehensive literature search.
anno %>%
kable(format = "html", col.names = colnames(anno)) %>%
kable_styling() %>%
kableExtra::scroll_box(width = "100%", height = "300px")
Type | Marker |
---|---|
Acinar | PRSS1 |
Acinar | REG1A |
Acinar | CPA1 |
Acinar | CPA2 |
Alpha | GCG |
Alpha | GC |
Alpha | TTR |
Beta | INS |
Beta | IGF2 |
Beta | IAPP |
Ductal | KRT19 |
Ductal | CFTR |
Ductal | SFRP5 |
Ductal | MMP7 |
Stellates_Mesenchymal | COL1A1 |
Stellates_Mesenchymal | PDGFRB |
Stellates_Mesenchymal | RGS10 |
Stellates_Mesenchymal | THY1 |
Endothelial | VWF |
Endothelial | CD93 |
Immune | NCF2 |
Immune | PTPRC |
PP_Gamma | PPY |
PP_Gamma | CARTPT |
PP_Gamma | PCDH10 |
PP_Gamma | PLAC8 |
Delta | SST |
Delta | LEPR |
Delta | PRG4 |
Epsilon | GHRL |
The scSorter method is based on a semi-supervised learning algorithm. It expects the pre-processed data as input. Therefore, we used the previously normalized, scaled and transformed expression matrix generated by SCT method as input. The top 3000 highly variable genes selected by SCT method was also given as input for scSorter method.
expr <- panc_new_sct@assays$SCT@data
topgenes <- head(panc_new_sct@assays$SCT@var.features, 3000)
topgene_filter = rowSums(expr[topgenes, ]!=0) > ncol(expr)*.1
topgenes = topgenes[topgene_filter]
## At last, we subset the preprocessed expression data and run scSorter.
picked_genes = unique(c(anno$Marker, topgenes))
expr = expr[rownames(expr) %in% picked_genes, ]
Based on the expression matrix and the marker genes the scSorter method is fit and the cell type assignment results predicted are stored in the Pred_Type vector.
rts <- scSorter(expr, anno)
panc_new_sct$cell_type <- rts$Pred_Type
The distribution for all cells across different cells are shown below. From the metrics, We can see that Acinar, Alpha, Beta, and Ductal are some of the major cell types.
table(rts$Pred_Type)
##
## Acinar Alpha Beta
## 59494 65113 44559
## Delta Ductal Endothelial
## 5669 20225 5852
## Epsilon Immune PP_Gamma
## 196 1198 2825
## Stellates_Mesenchymal Unknown
## 9587 7359
The celltype information is added to the metadata in the original Seurat object
cell_type.info <- data.frame(cell_type = panc_new_sct$cell_type, row.names= colnames(panc_new_sct_umap))
panc_new_sct_umap <- AddMetaData(object = panc_new_sct_umap, metadata = cell_type.info)
## Convert cell type to factor
panc_new_sct_umap$cell_type <- as.factor(panc_new_sct_umap$cell_type)
Idents(panc_new_sct_umap) <- "cell_type"
panc_new_sct_umap$ident <- NULL
Analyze the cell type composition across different disease groups and store results in the data frame.
df <- data.frame(panc_new_sct_umap@meta.data$cell_type, panc_new_sct_umap@meta.data$disease_state)
colnames(df) <- c("Cell_Type", "Condition")
df <- df %>% group_by(Condition, Cell_Type) %>%
summarise(Nb = n()) %>%
mutate(C = sum(Nb)) %>%
mutate(Percent = Nb/C*100)
df<-df[df$Cell_Type!="Unknown",]
# df$Condition <- gsub("Control", "CTL", df$Condition)
df$Cell_Type <- gsub("Stellates_Mesenchymal", "Stellates", df$Cell_Type)
df$Cell_Type <- gsub("PP_Gamma", "PP", df$Cell_Type)
The stacked bar plot showing the cell type composition in each group after pre-processing.
xtheme <- theme_bw()+ theme(plot.title = element_text(face = "bold" ,hjust = 0.5, size= 10)
,axis.text.y = element_text(face = "bold",angle = 0, size = 10, hjust=1)
,axis.title.y = element_text(face = "bold", size = rel(0.8))
,axis.text.x = element_text(face = "bold",angle = 0, size = 10)
,axis.title.x = element_text(face = "bold", size = rel(0.8))
,axis.ticks.x=element_blank(), strip.text = element_text(size=10))
ggplot(df, aes(fill=Condition, y=Percent, x=Cell_Type)) +
geom_bar(position="fill", stat="identity") + scale_fill_viridis(discrete = T) + xlab("") + xtheme +
theme(legend.position='top', axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1))
FeaturePlot(panc_new_sct_umap, features = c("PRSS1", "REG1A", "CPA1", "CPA2", "GCG",
"GC", "TTR", "INS", "IAPP", "GHRL",
"COL1A1", "PDGFRB", "RGS10", "THY1", "VWF",
"CD93", "PPY", "SST", "NCF2", "PTPRC"), pt.size = 0.2, ncol = 5) + theme(legend.position = 'none',
axis.title.x = element_blank(), axis.title.y = element_blank())
The UMAP showing the cell type annotations from the scSorter method
DimPlot(panc_new_sct_umap, group.by = "cell_type", reduction = "umap", label = FALSE, cols= c("#e30800", "#f56505", "#dec400", "#006630", "#0223c7","#5b02c7", "#00b0e6", "#c40080", "#02f00a", "#7d3301", "#000000"))
UMAP showing only Acinar cells
DimPlot(panc_new_sct_umap, group.by = "cell_type", reduction = "umap", label = FALSE, cols= c("#fac720", "#000000", "#000000", "#000000", "#000000","#000000", "#000000", "#000000", "#000000", "#000000", "#000000", "#000000"))
UMAP showing only Alpha cells
UMAP showing only Beta cells
UMAP showing only Ductal cells
UMAP showing only Immune cells