It took me 8+ months to finish the draft of the general pipelines. Afterwards, I optimized the pipeline to v3 version by comparing the results of different pipelines. However, as Seurat has already been updated to Seurat-v5, code might have to be modified before usage.

v1 version

v1 version
v1 version

10x_multione_workflow_v1.pdf

v3 version

v3 version
v3 version

10x_multione_workflow_v3.pdf


An integrated workflow to perform four v1-v4 version pipelines AT ONCE:

I previously developed four pipelines (v1–v4). This integrated workflow runs all four on new data so their results can be compared directly.

Compare the following workflows at once

  • v1 - cellranger-arc aggr + IntegrateData
  • v2 - cellranger-arc aggr + not IntegrateData
  • v3 - cellranger-arc count*2 + IntegrateData
  • v4 - cellranger-arc count*2 + not IntegrateData

Library and functions

library(Matrix)
library(Seurat)
library(Signac)
library(EnsDb.Mmusculus.v79)
library(dplyr)
library(tidyr)
library(ggplot2)
library(biovizBase)
library(RCurl)
library(AnnotationHub)
library(SoupX)
library(ExperimentHub)
library(SingleCellExperiment)
library(monocle3)
library(scuttle)
library(celldex)
library(scran)
library(viridis)
library(HGNChelper)
library(ggraph)
library(openxlsx)
library(metap)
library(purrr)
library(tibble)
library(velocyto.R)
library(SeuratWrappers)
library(stringr)

# load gene set preparation function
source("<https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/R/gene_sets_prepare.R>")

# load cell type annotation function
source("<https://raw.githubusercontent.com/IanevskiAleksandr/sc-type/master/R/sctype_score_.R>")

SoupX remove ambient RNA (with cluster info in outs data produced by cellranger)

runSoupX <- function(raw_counts, filtered_counts, mat_out_path){
  in_soup <- SoupChannel(tod = raw_counts[rownames(raw_counts) != "Gm42418",],
                         toc = filtered_counts[rownames(filtered_counts) != "Gm42418",],
                         metaData = NULL,
                         soupRange = c(0, 10),
                         keepDroplets = FALSE)
  # Gm42418 is a rRNA contaminant - remove it now

  sr_obj <- CreateSeuratObject(in_soup$toc)

  # Fast preliminary clustering and normalization for soupx run
  sr_obj <- NormalizeData(sr_obj)
  sr_obj <- FindVariableFeatures(sr_obj)
  sr_obj <- ScaleData(sr_obj)
  sr_obj <- RunPCA(sr_obj,pcs.compute=30)
  sr_obj <- RunUMAP(sr_obj,dims=1:15)
  sr_obj <- FindNeighbors(sr_obj,dims=1:15)
  sr_obj <- FindClusters(sr_obj,resolution=1.2)
  sr_DF <-  as.data.frame(sr_obj@reductions$umap@cell.embeddings)
  colnames(sr_DF) <- c('RD1','RD2')
  sr_DF$Cluster <- factor(sr_obj@meta.data[rownames(sr_DF),'RNA_snn_res.1.2'])

  #Specify background RNA genes
  background_RNA_genes <- c("Dcn", "Bgn", "Aspn", "Ecm2", "Fos", "Hbb-bs", "Hbb-bt", "Hba-a1", "Hba-a2", "Lyz1", "Lyz2", "Mgp", "Postn", "Scgb1a1")

  #Specify background RNA genes for epithelial specific cell sort
  est_expression <- estimateNonExpressingCells(in_soup,
                                               list(SLRP = background_RNA_genes),
                                               clusters = setNames(sr_DF$Cluster, rownames(sr_DF)),
                                               FDR = 0.05,
                                               maximumContamination = 1.5)

  ## calculate contamination and adjust the counts.
  in_soup <- setClusters(in_soup, sr_DF$Cluster)
  in_soup <- calculateContaminationFraction(in_soup, list(SLRP = background_RNA_genes), useToEst = est_expression, forceAccept = TRUE)
  head(in_soup$metaData)

  ## adjust the counts based on contamination fraction
  ## Return dgCMatrix
  #return(adjustCounts(in_soup, roundToInt = TRUE))
  adj_counts <- adjustCounts(in_soup)
  Matrix::writeMM(adj_counts, file = paste0(mat_out_path))
  return(adj_counts)
}

Import loom file

P5_loom_raw <- ReadVelocity(file = "###")
P5_loom_raw <- as.Seurat(x = P5_loom_raw)

P30_loom_raw <- ReadVelocity(file = "###")
P30_loom_raw <- as.Seurat(x = P30_loom_raw)

v1 and v2 raw data process

Import RNA assay and remove ambient RNA

mouse_lung_aggr <-
  runSoupX(
    Read10X_h5("###")$`Gene Expression`,
    Read10X_h5("###")$`Gene Expression`,
            "###")

mouse_lung_aggr <- CreateSeuratObject(counts = mouse_lung_aggr)

# 確認去除 Gm42418 gene
# rownames(mouse_lung@assays$RNA)[grep("^Gm42418", rownames(mouse_lung_aggr@assays$RNA), perl = TRUE)]

Gene-level filtering

DefaultAssay(mouse_lung_aggr) <- "RNA"

counts <- GetAssayData(object = mouse_lung_aggr, slot = "counts")
nonzero <- counts > 0

keep_genes <- Matrix::rowSums(nonzero) >= 10
filtered_counts <- counts[keep_genes, ]

mouse_lung_aggr <- CreateSeuratObject(filtered_counts, meta.data = mouse_lung_aggr@meta.data)

Process the cell ID in loom file

# 把 "P5_scRNA:" 去除
P5_loom_v1andV2 <- RenameCells(P5_loom_raw,
                             new.names = gsub(pattern = "^P5_scRNA:",
                                              replacement = "",
                                              colnames(P5_loom_raw))
)

# 把 "x" 改成 "-1"
P5_loom_v1andV2 <- RenameCells(P5_loom_v1andV2,
                             new.names = gsub(pattern = "x$",
                                              replacement = "-1",
                                              colnames(P5_loom_v1andV2))
)

# 檢查
#colnames(P5_loom_v1andV2)[1:10]



#### P30
# 把 "P30_scRNA:" 去除
P30_loom_v1andV2 <- RenameCells(P30_loom_raw,
                             new.names = gsub(pattern = "^P30_scRNA:",
                                              replacement = "",
                                              colnames(P30_loom_raw))
)

# 把 "x" 改成 "-2"
P30_loom_v1andV2 <- RenameCells(P30_loom_v1andV2,
                             new.names = gsub(pattern = "x$",
                                              replacement = "-2",
                                              colnames(P30_loom_v1andV2))
)

# 檢查
#colnames(P30_loom_v1andV2)[1:10]

loom_v1andV2 <- merge(P5_loom_v1andV2,P30_loom_v1andV2)

Find consensus cell ID between loom and Seurat object

# remove Gm42418 feature in loom file so the feature numbers is same as seurat RNA assays
counts <- GetAssayData(loom_v1andV2, assay = "spliced")
counts <- counts[-(which(rownames(counts) %in% c('Gm42418'))),]
loom_v1andV2 <- subset(loom_v1andV2, features = rownames(counts))



#  loom  與 seurat object 的 cell number 不一樣,而我只想要留下共同的 cell ID
# Pull cell names
CellID_seu <- colnames(mouse_lung_aggr)
CellID_loom <- colnames(loom_v1andV2)

# Identify shared cells between both objects
shared_cellIDs_V1andV2 <- intersect(x = CellID_seu, y = CellID_loom)

# filter both loom and seurat object
mouse_lung_aggr$cells <- colnames(mouse_lung_aggr)
mouse_lung_aggr <- subset(mouse_lung_aggr,
               subset = cells %in% shared_cellIDs_V1andV2)

loom_v1andV2$cells <- colnames(loom_v1andV2)
loom_v1andV2 <- subset(loom_v1andV2,
               subset = cells %in% shared_cellIDs_V1andV2)

Add loom to the Seurat object

counts slot

mouse_lung_aggr[["spliced"]] <- CreateAssayObject(counts = GetAssayData(object =  loom_v1andV2,
                                                            assay = "spliced",
                                                            slot = 'counts'))
mouse_lung_aggr[["unspliced"]] <- CreateAssayObject(counts = GetAssayData(object =  loom_v1andV2,
                                                            assay = "unspliced",
                                                            slot = 'counts'))
mouse_lung_aggr[["ambiguous"]] <- CreateAssayObject(counts = GetAssayData(object =  loom_v1andV2,
                                                            assay = "ambiguous",
                                                            slot = 'counts'))

Import ATAC assay and callpeaks

# the 10x hdf5 file contains both data types
# extract ATAC data
atac_counts <- Read10X_h5("###")$Peaks


# filter cell ID
atac_counts_filter <- atac_counts[,shared_cellIDs_V1andV2]



# Now add in the ATAC-seq data
grange.counts <- StringToGRanges(rownames(atac_counts_filter), sep = c(":", "-"))
# we'll only use peaks in standard chromosomes
grange.use <- seqnames(grange.counts) %in% standardChromosomes(grange.counts)
atac_counts_filter <- atac_counts_filter[as.vector(grange.use), ]


annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Mmusculus.v79)
seqlevelsStyle(annotations) <- 'UCSC'
genome(annotations) <- "mm10"



# filter cell ID in fragment file
Signac::FilterCells(
  fragments = "###",
  cells = shared_cellIDs_V1andV2,
  outfile = "###")

frag.file_filter_V1andV2 <- "###"


# add Chromatin Assay in seurat object
mouse_lung_aggr[["ATAC"]]  <- CreateChromatinAssay(
   counts = atac_counts_filter,
   sep = c(":", "-"),
   genome = 'mm10',
   fragments = frag.file_filter_V1andV2,
   min.cells = 10,
   annotation = annotations
 )



####### Callpeaks
DefaultAssay(mouse_lung_aggr) <- "ATAC"
mouse_lung_aggr@meta.data$sample <- NA
mouse_lung_aggr$cells <- colnames(mouse_lung_aggr)
mouse_lung_aggr@meta.data$sample[which(str_detect(mouse_lung_aggr@meta.data$cells, "-1$"))] <- "P5"
mouse_lung_aggr@meta.data$sample[which(str_detect(mouse_lung_aggr@meta.data$cells, "-2$"))] <- "P30"

# call peaks using MACS2
peaks_V1andV2 <- CallPeaks(mouse_lung_aggr,
									macs2.path = "/data/core/jordan/CondaEnv/macs2/bin/macs2",
									group.by = "sample",
									combine.peaks = TRUE)

# remove peaks on nonstandard chromosomes and in genomic blacklist regions
peaks_V1andV2 <- keepStandardChromosomes(peaks_V1andV2, pruning.mode = "coarse")
peaks_V1andV2 <- subsetByOverlaps(x = peaks_V1andV2, ranges = blacklist_mm10, invert = TRUE)

# Filter out bad peaks based on length
peakwidths <- width(peaks_V1andV2)
peaks_V1andV2 <- peaks_V1andV2[peakwidths  < 10000 & peakwidths > 20]


# quantify counts in each peak
macs2_counts_V1andV2 <- FeatureMatrix(fragments = Fragments(mouse_lung_aggr),
														  features = peaks_V1andV2,
														  cells = colnames(mouse_lung_aggr))

# create a new assay using the MACS2 peak set and add it to the Seurat object
mouse_lung_aggr[["peaks"]] <- CreateChromatinAssay(counts = macs2_counts_V1andV2,
																						  fragments = frag.file_filter_V1andV2,
																						  annotation = annotations)

Calculate NS, TSS, novelty score and percentage of reads that map to the mitochondrial genome

DefaultAssay(mouse_lung_aggr) <- "peaks"

# Calculate the strength of the nucleosome signal per cell. Computes the ratio of fragments between 147 bp and 294 bp (mononucleosome) to fragments < 147 bp (nucleosome-free)
mouse_lung_aggr <- NucleosomeSignal(mouse_lung_aggr)
mouse_lung_aggr$nucleosome_group <- ifelse(mouse_lung_aggr$nucleosome_signal > 1, 'NS > 1', 'NS < 1')
FragmentHistogram(object = mouse_lung_aggr, group.by = 'nucleosome_group', region = 'chr1-1-10000000')


# Compute the transcription start site (TSS) enrichment score for each cell
mouse_lung_aggr <- TSSEnrichment(mouse_lung_aggr, fast = FALSE)
mouse_lung_aggr$high.tss <- ifelse(mouse_lung_aggr$TSS.enrichment > 2.5, 'High', 'Low')
TSSPlot(mouse_lung_aggr, group.by = 'high.tss', assay = 'peaks') + NoLegend()


####
# calculate novelty score 並且另外把metadata移出來
mouse_lung_aggr$log10GenesPerUMI <- log10(mouse_lung_aggr$nFeature_RNA) / log10(mouse_lung_aggr$nCount_RNA)

# The percentage of reads that map to the mitochondrial genome
mouse_lung_aggr[["percent.mt"]] <- PercentageFeatureSet(mouse_lung_aggr, assay = "RNA", pattern = "^mt-")
mouse_lung_aggr$percent.mt <- mouse_lung_aggr$percent.mt/100

Cell-level filtering

mouse_lung_aggr_filter <- subset(
  x = mouse_lung_aggr,
  subset =
    nCount_peaks < 70000 &
    nCount_peaks > 500 &

    nCount_RNA > 500 &
    nCount_RNA < 8000 &
		nFeature_RNA > 200 &
    nFeature_RNA < 4000 &

		log10GenesPerUMI > 0.9 &
    percent.mt < 0.4 &
    percent.mt > 0.005 &

    nucleosome_signal < 1 &
    TSS.enrichment > 2.5
)

# after filtering:  ->  cells

Observe batch effect in RNA assay?

DefaultAssay(mouse_lung_aggr_filter) <- "RNA"

mouse_lung_aggr_filter <- NormalizeData(object =  mouse_lung_aggr_filter)
mouse_lung_aggr_filter <- FindVariableFeatures(object =  mouse_lung_aggr_filter, nfeatures = 16000)
mouse_lung_aggr_filter <- ScaleData(object =  mouse_lung_aggr_filter)
mouse_lung_aggr_filter <- RunPCA(object =  mouse_lung_aggr_filter)

#ElbowPlot(mouse_lung_aggr_filter) # 1:20 is enough

mouse_lung_aggr_filter <- RunUMAP(object =  mouse_lung_aggr_filter,
                             dims = 1:50,
                             umap.method = "uwot")
DimPlot(mouse_lung_aggr_filter,
        reduction = "umap",
        group.by = "sample") +
  ggtitle("RNA assay: simple-normalize umap of v1 and v2 (cellranger-arc aggr)")
Observe batch effect in RNA assay?
Observe batch effect in RNA assay?

Observe batch effect in peaks assay?

DefaultAssay(mouse_lung_aggr_filter) <- "peaks"


# Observe batch effect in peaks assay
# q5: top 95% most common features
mouse_lung_aggr_filter <- FindTopFeatures(mouse_lung_aggr_filter, min.cutoff = "q5")
mouse_lung_aggr_filter <- RunTFIDF(mouse_lung_aggr_filter)
mouse_lung_aggr_filter <- RunSVD(mouse_lung_aggr_filter)
mouse_lung_aggr_filter <- RunUMAP(object = mouse_lung_aggr_filter,
                                  reduction = "lsi",
                                  reduction.name = "atac_umap",
                                  dims = 2:50)

DimPlot(mouse_lung_aggr_filter,
        reduction = "atac_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("peaks assay: normalize umap (all sample at once)\\n of v1 and v2 (cellranger-arc aggr)")
Observe batch effect in peaks assay?
Observe batch effect in peaks assay?

Regress out Cell cycle effects

get canonical markers for mouse cell cycle

# Download cell cycle genes for organism at <https://github.com/hbc/tinyatlas/tree/master/cell_cycle>. Read it in with:

cc_file <- getURL("<https://raw.githubusercontent.com/hbc/tinyatlas/master/cell_cycle/Mus_musculus.csv>")
cell_cycle_genes <- read.csv(text = cc_file)



# Connect to AnnotationHub
ah <- AnnotationHub()

# Access the Ensembl database for organism
ahDb <- query(ah,
              pattern = c("Mus musculus", "EnsDb"),
              ignore.case = TRUE)

# Acquire the latest annotation files
id <- ahDb %>%
        mcols() %>%
        rownames() %>%
        tail(n = 1)

# Download the appropriate Ensembldb database
edb <- ah[[id]]

# Extract gene-level information from database
annotations_markerG <- genes(edb,
                     return.type = "data.frame")

# Select annotations of interest
annotations_markerG <- annotations_markerG %>%
        dplyr::select(gene_id, gene_name, seq_name, gene_biotype, description)


# Get gene names for Ensembl IDs for each gene
cell_cycle_markers <- dplyr::left_join(cell_cycle_genes, annotations_markerG, by = c("geneID" = "gene_id"))

# Acquire the S phase genes
s_genes <- cell_cycle_markers %>%
        dplyr::filter(phase == "S") %>%
        pull("gene_name")

# Acquire the G2M phase genes
g2m_genes <- cell_cycle_markers %>%
        dplyr::filter(phase == "G2/M") %>%
        pull("gene_name")

Perform cell cycle scoring

DefaultAssay(mouse_lung_aggr_filter) <- "RNA"


# Perform cell cycle scoring
seurat_phase_V1andV2 <- CellCycleScoring(mouse_lung_aggr_filter,
                                 g2m.features = g2m_genes,
                                 s.features = s_genes)

# Perform PCA and color by cell cycle phase
# but first, 確定 Variable features have 有被 set:

#seurat_phase <- FindVariableFeatures(seurat_phase,
#                     selection.method = "vst",
#                     nfeatures = 8000,
#                     verbose = FALSE)


# 測試 regress 前後的差異

# if not regress out cell cycle effect
seurat_phase_V1andV2_NonRegress <- ScaleData(seurat_phase_V1andV2,
                                     features = rownames(seurat_phase_V1andV2))

seurat_phase_V1andV2_NonRegress <- RunPCA(seurat_phase_V1andV2_NonRegress,
                                          features = c(s_genes, g2m_genes))


# if Regress out cell cycle effect
seurat_phase_V1andV2_Regress <- ScaleData(seurat_phase_V1andV2,
                          vars.to.regress = c("S.Score", "G2M.Score"),
                          features = rownames(seurat_phase_V1andV2))
seurat_phase_V1andV2_Regress <- RunPCA(seurat_phase_V1andV2_Regress,
                               features = c(s_genes, g2m_genes))



DimPlot(seurat_phase_V1andV2_NonRegress,
        reduction = "pca",
        group.by= "Phase") +
  ggtitle("v1 and v2: not regress out cell cycle effects")

DimPlot(seurat_phase_V1andV2_Regress,
        reduction = "pca",
        group.by= "Phase") +
  ggtitle("v1 and v2: regress out cell cycle effects")
Perform cell cycle scoring
Perform cell cycle scoring
Perform cell cycle scoring
Perform cell cycle scoring

v1 workflow (IntegrateData)

Split and SCTransform (regress out unwanted variation)

# 把剛剛 seurat_phase計算的 s_genes與 g2m_genes資料加入到__中
mouse_lung_v1 <- mouse_lung_aggr_filter
mouse_lung_v1@meta.data <- seurat_phase_V1andV2_Regress@meta.data



DefaultAssay(mouse_lung_v1) <- "RNA"

# split object
split_seurat <- SplitObject(mouse_lung_v1, split.by = "sample")

# SCTransform n=16000 var features for each object
rna.list <- lapply(X = split_seurat, function(x){
   CreateSeuratObject(x@assays$RNA@counts, meta.data = x@meta.data) %>%
   SCTransform(vst.flavor="v2",
               vars.to.regress = c("S.Score", "G2M.Score", "percent.mt"),
               verbose = TRUE,
               ncells = 5000,
               variable.features.n = 16000)
})

# Select the most variable features to use for integration
integ_features <- SelectIntegrationFeatures(object.list = rna.list,
                                            nfeatures = length(rna.list$P5@assays$SCT@var.features))

# Prepare the SCT list object for integration
rna.list <- PrepSCTIntegration(object.list = rna.list,
                                   anchor.features = integ_features)


# perform CCA integration
# find the best buddies or anchors and filter incorrect anchors.
anchors.sct.norm <- FindIntegrationAnchors(object.list = rna.list,
                                           normalization.method = "SCT",
                                           anchor.features = integ_features,
                                           n.trees = 100)

combined.sct_v1 <- IntegrateData(anchorset = anchors.sct.norm,
                              normalization.method = "SCT")

# now the defaultAssay is "integrated"
# if not scaled yet, do:
# combined.sct <- ScaleData(combined.sct)

combined.sct_v1 <- RunPCA(object = combined.sct_v1,
                       reduction.name = "integrated_pca")
combined.sct_v1 <- RunUMAP(combined.sct_v1,
                        dims = 1:50,
                        reduction = "integrated_pca",
                        reduction.name = "integrated_umap")

# Given a merged object with multiple SCT models, this function uses minimum of the median UMI (calculated using the raw UMI counts) of individual objects to reverse the individual SCT regression model using minimum of median UMI as the sequencing depth covariate. The counts slot of the SCT assay is replaced with recorrected counts and the data slot is replaced with log1p of recorrected counts.
combined.sct.consistent_v1 <- PrepSCTFindMarkers(combined.sct_v1,
                                                 assay = 'SCT')

DimPlot(combined.sct.consistent_v1,
        label = TRUE,
        reduction = 'integrated_umap',
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v1: RNA integrated umap")
Split and SCTransform (regress out unwanted variation)
Split and SCTransform (regress out unwanted variation)

Split and normalization (peaks assay)

DefaultAssay(mouse_lung_aggr_filter) <- "peaks"
DefaultAssay(mouse_lung_v1) <- "peaks"

# split
obj.list <- SplitObject(mouse_lung_v1, split.by = "sample")

# normalization of each
# make sure to keep peak counts > 0
atac.list <- lapply(X = obj.list, function(x){
    peak_keep = which(rowSums(x@assays$peaks@counts) > 0)
    CreateSeuratObject(x@assays$peaks@counts[peak_keep,],
                       meta.data = x@meta.data,
                       assay = 'peaks')   %>%
        FindTopFeatures(min.cutoff = "q5") %>%
        RunTFIDF() %>%
        RunSVD()
})



# integration
# find integration anchors
integration.anchors <- FindIntegrationAnchors(
  object.list = atac.list,
  reduction = "rlsi",
  anchor.features = rownames(atac.list$P5),
  dims = 2:50,
  n.trees = 30)

# integrate LSI embeddings
atac.integrated_v1 <- IntegrateEmbeddings(
                        anchorset = integration.anchors,
                        reductions = mouse_lung_aggr_filter[["lsi"]],
                        new.reduction.name = "integrated_lsi",
                        dims.to.integrate = 1:50)



atac.integrated_v1 <- RunUMAP(atac.integrated_v1,
                           reduction = 'integrated_lsi',
                           dims = 2:50,
                           reduction.name = "atac_integrated_umap")


DimPlot(atac.integrated_v1,
        reduction = "atac_integrated_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v1: peaks integrated umap")
Split and normalization (peaks assay)
Split and normalization (peaks assay)

Combine all assays

integrated_multiome_v1 <- combined.sct.consistent_v1

integrated_multiome_v1[["peaks"]]  <- CreateChromatinAssay(
                        counts = atac.integrated_v1@assays$peaks@counts,
                        sep = c(":", "-"),
                        genome = 'mm10',
                        fragments = frag.file_filter_V1andV2,
                        annotation = annotations)


integrated_multiome_v1[["spliced"]] <- CreateAssayObject(counts = GetAssayData(
                                                                    object =  mouse_lung_v1,
                                                                    assay = "spliced",
                                                                    slot = 'data'))
integrated_multiome_v1[["unspliced"]] <- CreateAssayObject(counts = GetAssayData(
                                                                    object =  mouse_lung_v1,
                                                                    assay = "unspliced",
                                                                    slot = 'data'))
integrated_multiome_v1[["ambiguous"]] <- CreateAssayObject(counts = GetAssayData(
                                                                    object =  mouse_lung_v1,
                                                                    assay = "ambiguous",
                                                                    slot = 'data'))



integrated_multiome_v1@reductions <- append(combined.sct.consistent_v1@reductions,
                                          atac.integrated_v1@reductions)

WNN

integrated_multiome_v1 <- FindMultiModalNeighbors(integrated_multiome_v1,
                                               reduction.list = list("integrated_pca",
                                                                     "integrated_lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v1 <- RunUMAP(integrated_multiome_v1,
                                nn.name = "weighted.nn",
                                reduction.name = "wnn_umap",
                                return.model=TRUE)
# res = 1
integrated_multiome_v1 <- FindClusters(integrated_multiome_v1,
                                    graph.name = "wsnn",
                                    algorithm = 3,
                                    verbose = FALSE,
                                    resolution = 1)

# WNN clustering
DimPlot(integrated_multiome_v1,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
ggtitle("v1: WNN clustering")

DimPlot(integrated_multiome_v1,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "wsnn_res.1") +
  ggtitle("v1: WNN clustering (res:1)")
WNN
WNN
WNN
WNN

v2 workflow (without IntegrateData)

SCTransform without IntegrateData

SCTransform samples separately

https://github.com/satijalab/sctransform/issues/55#issuecomment-633843730

# 把剛剛 seurat_phase計算的 s_genes與 g2m_genes資料加入到__中
mouse_lung_v2 <- mouse_lung_aggr_filter
mouse_lung_v2@meta.data <- seurat_phase_V1andV2_Regress@meta.data
DefaultAssay(mouse_lung_v2) <- "RNA"


# split object
split_seurat <- SplitObject(mouse_lung_v2, split.by = "sample")

# SCTransform n=16000 var features for each object
rna.list <- lapply(X = split_seurat, function(x){
   CreateSeuratObject(x@assays$RNA@counts, meta.data = x@meta.data) %>%
   SCTransform(vst.flavor="v2",
               vars.to.regress = c("S.Score", "G2M.Score", "percent.mt"),
               verbose = TRUE,
               ncells = 5000,
               variable.features.n = 16000)
})


my_select_features_v2 <- SelectIntegrationFeatures(rna.list,
                                                nfeatures = 16000,
                                                assay = c("SCT","SCT"),
                                                verbose = TRUE)

combined.sct.consistent_v2 <- PrepSCTFindMarkers(merge(rna.list$P5,
                                                       rna.list$P30),
                                                 assay = 'SCT')


DefaultAssay(combined.sct.consistent_v2) <- "SCT"
VariableFeatures(combined.sct.consistent_v2) <- my_select_features_v2

combined.sct.consistent_v2 <- RunPCA(object = combined.sct.consistent_v2,
                                reduction.name = "SCT_pca")

combined.sct.consistent_v2 <- RunUMAP(combined.sct.consistent_v2,
                                 dims = 1:25,
                                 reduction = "SCT_pca",
                                 reduction.name = "SCT_umap")

DimPlot(combined.sct.consistent_v2,
        label = TRUE,
        reduction = 'SCT_umap',
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v2: RNA non-integrated umap")
https://github.com/satijalab/sctransform/issues/55#issuecomment-633843730
https://github.com/satijalab/sctransform/issues/55#issuecomment-633843730

peaks

# split
obj.list <- SplitObject(mouse_lung_v2, split.by = "sample")

# normalization of each
# make sure to keep peak counts > 0
atac.list <- lapply(X = obj.list, function(x){

    peak_keep = which(rowSums(x@assays$peaks@counts) > 0)
    CreateSeuratObject(x@assays$peaks@counts[peak_keep,],
                       meta.data = x@meta.data,
                       assay = 'peaks')   %>%
        FindTopFeatures(min.cutoff = "q5") %>%
        RunTFIDF()
})

atac.integrated_v2 <- merge(atac.list$P5, atac.list$P30)
atac.integrated_v2 <- FindTopFeatures(atac.integrated_v2, min.cutoff = "q5")
atac.integrated_v2 <- RunSVD(atac.integrated_v2)
atac.integrated_v2 <- RunUMAP(atac.integrated_v2,
                           reduction = 'lsi',
                           dims = 2:50,
                           reduction.name = "peaks_umap")


DimPlot(atac.integrated_v2,
        reduction = "peaks_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v2: peaks non-integrated umap")
peaks
peaks

Combine all assays

integrated_multiome_v2 <- atac.integrated_v2


# move just the "data" slots!!!!!!
integrated_multiome_v2[["RNA"]]  <- CreateAssayObject(counts = GetAssayData(
                                                              object =  combined.sct.consistent_v2,
                                                              assay = "RNA",
                                                              slot =  "counts"))
integrated_multiome_v2[["SCT"]]  <- CreateAssayObject(counts = GetAssayData(
                                                              object =  combined.sct.consistent_v2,
                                                              assay = "SCT",
                                                              slot =  "data"))

# 所以這邊最後integrated_multiome裏面
# SCT assay 的 "counts" slot 其實顯示的數值就跟其 "data" slot 一樣

# 要再把 mouse_lung_filter_SCT 的 SCT assay counts slot 複製過來
integrated_multiome_v2@assays$SCT@counts <- combined.sct.consistent_v2@assays$SCT@counts

integrated_multiome_v2@reductions <- append(integrated_multiome_v2@reductions,
                                            combined.sct.consistent_v2@reductions)

WNN analysis


integrated_multiome_v2 <- FindMultiModalNeighbors(integrated_multiome_v2,
                                               reduction.list = list("SCT_pca",
                                                                     "lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v2 <- RunUMAP(integrated_multiome_v2,
                                nn.name = "weighted.nn",
                                reduction.name = "wnn_umap",
                                return.model=TRUE)
# res = 1
integrated_multiome_v2 <- FindClusters(integrated_multiome_v2,
                                    graph.name = "wsnn",
                                    algorithm = 3,
                                    verbose = FALSE,
                                    resolution = 1)



# WNN clustering
DimPlot(integrated_multiome_v2,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
ggtitle("v2: WNN clustering")

DimPlot(integrated_multiome_v2,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "wsnn_res.1") +
  ggtitle("v2: WNN clustering (res:1)")
WNN analysis
WNN analysis
WNN analysis
WNN analysis

v3 and v4 raw data process

Import RNA assay from cellranger-arc count results

mouse_lung_count_P5 <-
  runSoupX(
    Read10X_h5("###")$`Gene Expression`,
    Read10X_h5("###")$`Gene Expression`,
            "###")


mouse_lung_count_P30 <-
  runSoupX(
    Read10X_h5("###")$`Gene Expression`,
    Read10X_h5("###")$`Gene Expression`,
            "###")



mouse_lung_count_P5 <- CreateSeuratObject(counts = mouse_lung_count_P5)
mouse_lung_count_P30 <- CreateSeuratObject(counts = mouse_lung_count_P30)

# 確認去除 Gm42418 gene
# rownames(mouse_lung_P5@assays$RNA)[grep("^Gm42418", rownames(mouse_lung_P5@assays$RNA), perl = TRUE)] # rownames(mouse_lung_P30@assays$RNA)[grep("^Gm42418", rownames(mouse_lung_P30@assays$RNA), perl = TRUE)]



# 由於 P5 P30 的細胞 ID 會完全一樣,所以要更改 P30 的 cell ID 成 "xxxxxx-2"
mouse_lung_count_P30 <- RenameCells(mouse_lung_count_P30,
                             new.names = gsub(pattern = "-1$",
                                              replacement = "-2",
                                              colnames(mouse_lung_count_P30))
)



mouse_lung_count <- merge(mouse_lung_count_P5,
                    mouse_lung_count_P30)

gene-level filtering

DefaultAssay(mouse_lung_count) <- "RNA"

counts <- GetAssayData(object = mouse_lung_count, slot = "counts")
nonzero <- counts > 0

keep_genes <- Matrix::rowSums(nonzero) >= 10
filtered_counts <- counts[keep_genes, ]

mouse_lung_count <- CreateSeuratObject(filtered_counts,
                                       meta.data = mouse_lung_count@meta.data)

Process the cell ID in loom file (have to do it again?)

# 把 "P5_scRNA:" 去除
P5_loom_V3andV4 <- RenameCells(P5_loom_raw,
                             new.names = gsub(pattern = "^P5_scRNA:",
                                              replacement = "",
                                              colnames(P5_loom_raw))
)

# 把 "x" 改成 "-1"
P5_loom_V3andV4 <- RenameCells(P5_loom_V3andV4,
                             new.names = gsub(pattern = "x$",
                                              replacement = "-1",
                                              colnames(P5_loom_V3andV4))
)


#### P30
# 把 "P30_scRNA:" 去除
P30_loom_V3andV4 <- RenameCells(P30_loom_raw,
                             new.names = gsub(pattern = "^P30_scRNA:",
                                              replacement = "",
                                              colnames(P30_loom_raw))
)

# 把 "x" 改成 "-2"
P30_loom_V3andV4 <- RenameCells(P30_loom_V3andV4,
                             new.names = gsub(pattern = "x$",
                                              replacement = "-2",
                                              colnames(P30_loom_V3andV4))
)

loom_V3andV4 <- merge(P5_loom_V3andV4,
                      P30_loom_V3andV4)

Find consensus cell ID between loom and Seurat object (have to do it again?)

# remove Gm42418 feature in loom file so the feature numbers is same as seurat RNA assays
counts <- GetAssayData(loom_V3andV4, assay = "spliced")
counts <- counts[-(which(rownames(counts) %in% c('Gm42418'))),]
loom_V3andV4 <- subset(loom_V3andV4, features = rownames(counts))



# Pull cell names
CellID_seu <- colnames(mouse_lung_count)
CellID_loom <- colnames(loom_V3andV4)

# Identify shared cells between both objects
shared_cellIDs_V3andV4 <- intersect(x = CellID_seu,
                            y = CellID_loom)

# filter both loom and seurat object
mouse_lung_count$cells <- colnames(mouse_lung_count)
mouse_lung_count <- subset(mouse_lung_count,
               subset = cells %in% shared_cellIDs_V3andV4)

loom_V3andV4$cells <- colnames(loom_V3andV4)
loom_V3andV4 <- subset(loom_V3andV4,
               subset = cells %in% shared_cellIDs_V3andV4)

Import ATAC assay and callpeaks

# the 10x hdf5 file contains both data types
# extract ATAC data
atac_counts_P5 <- Read10X_h5("###")$Peaks
atac_counts_P30 <- Read10X_h5("###")$Peaks



# P5
# Now add in the ATAC-seq data
grange.counts <- StringToGRanges(rownames(atac_counts_P5), sep = c(":", "-"))
# we'll only use peaks in standard chromosomes
grange.use <- seqnames(grange.counts) %in% standardChromosomes(grange.counts)
atac_counts_P5 <- atac_counts_P5[as.vector(grange.use), ]


annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Mmusculus.v79)
seqlevelsStyle(annotations) <- 'UCSC'
genome(annotations) <- "mm10"


# add Chromatin Assay in seurat object
atac_assay_P5  <- CreateChromatinAssay(
   counts = atac_counts_P5,
   sep = c(":", "-"),
   genome = 'mm10',
   fragments = "###",
   min.cells = 10,
   annotation = annotations
 )

atac_P5 <- CreateSeuratObject(counts = atac_assay_P5, assay = "ATAC")

# filter
atac_P5$cells <- colnames(atac_P5)
atac_filter_P5 <- subset(atac_P5,
                         subset = cells %in% shared_cellIDs_V3andV4)







# P30
# Now add in the ATAC-seq data
grange.counts <- StringToGRanges(rownames(atac_counts_P30), sep = c(":", "-"))
# we'll only use peaks in standard chromosomes
grange.use <- seqnames(grange.counts) %in% standardChromosomes(grange.counts)
atac_counts_P30 <- atac_counts_P30[as.vector(grange.use), ]


# add Chromatin Assay in seurat object
atac_assay_P30  <- CreateChromatinAssay(
   counts = atac_counts_P30,
   sep = c(":", "-"),
   genome = 'mm10',
   fragments = "###",
   min.cells = 10,
   annotation = annotations
 )

atac_P30 <- CreateSeuratObject(counts = atac_assay_P30,
                               assay = "ATAC")


# rename the atac_P30
atac_P30 <- RenameCells(atac_P30,
                             new.names = gsub(pattern = "-1$",
                                              replacement = "-2",
                                              colnames(atac_P30)))


# filter
atac_P30$cells <- colnames(atac_P30)
atac_filter_P30 <- subset(atac_P30,
                          subset = cells %in% shared_cellIDs_V3andV4)


#################################
atac_V3andV4 <- merge(atac_filter_P5,
                      atac_filter_P30)

Callpeaks


DefaultAssay(atac_V3andV4) <- "ATAC"
atac_V3andV4@meta.data$sample <- NA
atac_V3andV4$cells <- colnames(atac_V3andV4)
atac_V3andV4@meta.data$sample[which(str_detect(atac_V3andV4@meta.data$cells, "-1$"))] <- "P5"
atac_V3andV4@meta.data$sample[which(str_detect(atac_V3andV4@meta.data$cells, "-2$"))] <- "P30"





# call peaks using MACS2
peaks_V3andV4 <- CallPeaks(atac_V3andV4,
									macs2.path = "/data/core/jordan/CondaEnv/macs2/bin/macs2",
									group.by = "sample",
									combine.peaks = TRUE)

# remove peaks on nonstandard chromosomes and in genomic blacklist regions
peaks_V3andV4 <- keepStandardChromosomes(peaks_V3andV4, pruning.mode = "coarse")
peaks_V3andV4 <- subsetByOverlaps(x = peaks_V3andV4, ranges = blacklist_mm10, invert = TRUE)

# Filter out bad peaks based on length
peakwidths <- width(peaks_V3andV4)
peaks_V3andV4 <- peaks_V3andV4[peakwidths  < 10000 & peakwidths > 20]


# quantify counts in each peak
macs2_counts_V3andV4 <- FeatureMatrix(fragments = Fragments(atac_V3andV4),
														  features = peaks_V3andV4,
														  cells = colnames(atac_V3andV4))

Separate P5 and P30, then use their corresponding fragment files in CreateChromatinAssay

# P5
macs2_counts_V3andV4_P5 <- macs2_counts_V3andV4[,which(str_detect(colnames(macs2_counts_V3andV4), "-1$"))]

# 因為這邊是已經filter 的 Cell ID,所以需要 filter fragment file
Signac::FilterCells(fragments = "###",
            cells = colnames(macs2_counts_V3andV4_P5),
            outfile = "###")

frag.file_filter_V3andV4_P5 <- "###"



# create a new assay using the MACS2 peak set and add it to the Seurat object
peaks_assay_V3andV4_P5 <- CreateChromatinAssay(counts = macs2_counts_V3andV4_P5,
                                       fragments = frag.file_filter_V3andV4_P5,
						                           annotation = annotations)
peaks_V3andV4_P5 <- CreateSeuratObject(counts = peaks_assay_V3andV4_P5,
                               assay = "peaks")



##########################################################################################
##########################################################################################
# P30 要注意我前面有把 P30 從 "-1" 改成 "-2",但 fragment file 沒有這樣更改
# 所以還是要先改為 "-1"
macs2_counts_V3andV4_P30 <- macs2_counts_V3andV4[,which(str_detect(colnames(macs2_counts_V3andV4), "-2$"))]

colnames(macs2_counts_V3andV4_P30) <- gsub(pattern = "-2$",
                                              replacement = "-1",
                                              colnames(macs2_counts_V3andV4_P30))

# 因為這邊是已經filter 的 Cell ID,所以需要 filter fragment file
Signac::FilterCells(fragments = "###",
            cells = colnames(macs2_counts_V3andV4_P30),
            outfile = "###")


frag.file_filter_V3andV4_P30 <- "###"




# create a new assay using the MACS2 peak set and add it to the Seurat object
peaks_assay_V3andV4_P30 <- CreateChromatinAssay(counts = macs2_counts_V3andV4_P30,
                                        fragments = frag.file_filter_V3andV4_P30,
						                            annotation = annotations)

peaks_V3andV4_P30 <- CreateSeuratObject(counts = peaks_assay_V3andV4_P30,
                                assay = "peaks")


# 改回為 "-2"
peaks_V3andV4_P30 <- RenameCells(peaks_V3andV4_P30,
                             new.names = gsub(pattern = "-1$",
                                              replacement = "-2",
                                              colnames(peaks_V3andV4_P30)))





peaks_V3andV4 <- merge(peaks_V3andV4_P5,
                       peaks_V3andV4_P30)



# combine all seurat objects (non-normalied "counts" slot)
peaks_V3andV4[["RNA"]] <- CreateAssayObject(counts = GetAssayData(object =  mouse_lung_count,
                                                            assay = "RNA",
                                                            slot = 'counts'))
peaks_V3andV4[["spliced"]] <- CreateAssayObject(counts = GetAssayData(object =  loom_V3andV4,
                                                            assay = "spliced",
                                                            slot = 'counts'))
peaks_V3andV4[["unspliced"]] <- CreateAssayObject(counts = GetAssayData(object =  loom_V3andV4,
                                                            assay = "unspliced",
                                                            slot = 'counts'))
peaks_V3andV4[["ambiguous"]] <- CreateAssayObject(counts = GetAssayData(object =  loom_V3andV4,
                                                            assay = "ambiguous",
                                                            slot = 'counts'))
mouse_lung_count <- peaks_V3andV4

Calculate NS, TSS, novelty score and percentage of reads that map to the mitochondrial genome

DefaultAssay(mouse_lung_count) <- "peaks"

# Calculate the strength of the nucleosome signal per cell. Computes the ratio of fragments between 147 bp and 294 bp (mononucleosome) to fragments < 147 bp (nucleosome-free)
mouse_lung_count <- NucleosomeSignal(mouse_lung_count)
mouse_lung_count$nucleosome_group <- ifelse(mouse_lung_count$nucleosome_signal > 1, 'NS > 1', 'NS < 1')
FragmentHistogram(object = mouse_lung_count, group.by = 'nucleosome_group', region = 'chr1-1-10000000')


# Compute the transcription start site (TSS) enrichment score for each cell
mouse_lung_count <- TSSEnrichment(mouse_lung_count, fast = FALSE)
mouse_lung_count$high.tss <- ifelse(mouse_lung_count$TSS.enrichment > 2.5, 'High', 'Low')
TSSPlot(mouse_lung_count, group.by = 'high.tss', assay = 'peaks') + NoLegend()




####
# calculate novelty score 並且另外把metadata移出來
mouse_lung_count$log10GenesPerUMI <- log10(mouse_lung_count$nFeature_RNA) / log10(mouse_lung_count$nCount_RNA)

# The percentage of reads that map to the mitochondrial genome
mouse_lung_count[["percent.mt"]] <- PercentageFeatureSet(mouse_lung_count, assay = "RNA", pattern = "^mt-")
mouse_lung_count$percent.mt <- mouse_lung_count$percent.mt/100

Cell-level filtering

mouse_lung_count_filter <- subset(
  x = mouse_lung_count,
  subset =
    nCount_peaks < 70000 &
    nCount_peaks > 500 &

    nCount_RNA > 500 &
    nCount_RNA < 8000 &
		nFeature_RNA > 200 &
    nFeature_RNA < 4000 &

		log10GenesPerUMI > 0.9 &
    percent.mt < 0.4 &
    percent.mt > 0.005 &

    nucleosome_signal < 1 &
    TSS.enrichment > 2.5
)
# after filtering: 13472  ->  9472 cells

Observe batch effect in RNA assay?

DefaultAssay(mouse_lung_count_filter) <- "RNA"

mouse_lung_count_filter@meta.data$sample <- NA
mouse_lung_count_filter$cells <- colnames(mouse_lung_count_filter)
mouse_lung_count_filter@meta.data$sample[which(str_detect(mouse_lung_count_filter@meta.data$cells, "-1$"))] <- "P5"
mouse_lung_count_filter@meta.data$sample[which(str_detect(mouse_lung_count_filter@meta.data$cells, "-2$"))] <- "P30"


mouse_lung_count_filter <- NormalizeData(object =  mouse_lung_count_filter)
mouse_lung_count_filter <- FindVariableFeatures(object =  mouse_lung_count_filter, nfeatures = 16000)
mouse_lung_count_filter <- ScaleData(object =  mouse_lung_count_filter)
mouse_lung_count_filter <- RunPCA(object =  mouse_lung_count_filter)

#ElbowPlot(mouse_lung_count_filter) # 1:20 is enough

mouse_lung_count_filter <- RunUMAP(object =  mouse_lung_count_filter,
                             dims = 1:50,
                             umap.method = "uwot")
DimPlot(mouse_lung_count_filter,
        reduction = "umap",
        group.by = "sample") +
  ggtitle("RNA assay: simple-normalize umap of v3 and v4 (cellranger-arc count*2)")
Observe batch effect in RNA assay?
Observe batch effect in RNA assay?

Observe batch effect in peaks assay?

DefaultAssay(mouse_lung_count_filter) <- "peaks"


# Observe batch effect in peaks assay
# q5: top 95% most common features
mouse_lung_count_filter <- FindTopFeatures(mouse_lung_count_filter, min.cutoff = "q5")
mouse_lung_count_filter <- RunTFIDF(mouse_lung_count_filter)
mouse_lung_count_filter <- RunSVD(mouse_lung_count_filter)
mouse_lung_count_filter <- RunUMAP(object = mouse_lung_count_filter,
                                  reduction = "lsi",
                                  reduction.name = "atac_umap",
                                  dims = 2:50)

DimPlot(mouse_lung_count_filter,
        reduction = "atac_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("peaks assay: normalize umap (all sample at once)\\n of v3 and v4 (cellranger-arc count*2)")
Observe batch effect in peaks assay?
Observe batch effect in peaks assay?

Perform cell cycle scoring

DefaultAssay(mouse_lung_count_filter) <- "RNA"


# Perform cell cycle scoring
seurat_phase_V3andV4 <- CellCycleScoring(mouse_lung_count_filter,
                                 g2m.features = g2m_genes,
                                 s.features = s_genes)

# Perform PCA and color by cell cycle phase
# but first, 確定 Variable features have 有被 set:

#seurat_phase <- FindVariableFeatures(seurat_phase,
#                     selection.method = "vst",
#                     nfeatures = 8000,
#                     verbose = FALSE)


# 測試 regress 前後的差異

# if not regress out cell cycle effect
seurat_phase_V3andV4_NonRegress <- ScaleData(seurat_phase_V3andV4,
                                     features = rownames(seurat_phase_V3andV4))

seurat_phase_V3andV4_NonRegress <- RunPCA(seurat_phase_V3andV4_NonRegress,
                                          features = c(s_genes, g2m_genes))


# if Regress out cell cycle effect
seurat_phase_V3andV4_Regress <- ScaleData(seurat_phase_V3andV4,
                          vars.to.regress = c("S.Score", "G2M.Score"),
                          features = rownames(seurat_phase_V3andV4))
seurat_phase_V3andV4_Regress <- RunPCA(seurat_phase_V3andV4_Regress,
                               features = c(s_genes, g2m_genes))



DimPlot(seurat_phase_V3andV4_NonRegress,
        reduction = "pca",
        group.by= "Phase") +
  ggtitle("v3 and v4: not regress out cell cycle effects")

DimPlot(seurat_phase_V3andV4_Regress,
        reduction = "pca",
        group.by= "Phase") +
  ggtitle("v3 and v4: regress out cell cycle effects")
Perform cell cycle scoring
Perform cell cycle scoring
Perform cell cycle scoring
Perform cell cycle scoring

v3 workflow (IntegrateData)

split and SCTransform (regress out unwanted variation)

# 把剛剛 seurat_phase計算的 s_genes與 g2m_genes資料加入到__中
mouse_lung_v3 <- mouse_lung_count_filter
mouse_lung_v3@meta.data <- seurat_phase_V3andV4_Regress@meta.data



DefaultAssay(mouse_lung_v3) <- "RNA"

# split object
split_seurat <- SplitObject(mouse_lung_v3, split.by = "sample")

# SCTransform n=16000 var features for each object
rna.list <- lapply(X = split_seurat, function(x){
   CreateSeuratObject(x@assays$RNA@counts, meta.data = x@meta.data) %>%
   SCTransform(vst.flavor="v2",
               vars.to.regress = c("S.Score", "G2M.Score", "percent.mt"),
               verbose = TRUE,
               ncells = 5000,
               variable.features.n = 16000)
})

# Select the most variable features to use for integration
integ_features <- SelectIntegrationFeatures(object.list = rna.list,
                                            nfeatures = length(rna.list$P5@assays$SCT@var.features))

# Prepare the SCT list object for integration
rna.list <- PrepSCTIntegration(object.list = rna.list,
                                   anchor.features = integ_features)


# perform CCA integration
# find the best buddies or anchors and filter incorrect anchors.
anchors.sct.norm <- FindIntegrationAnchors(object.list = rna.list,
                                           normalization.method = "SCT",
                                           anchor.features = integ_features,
                                           n.trees = 100)

combined.sct_v3 <- IntegrateData(anchorset = anchors.sct.norm,
                              normalization.method = "SCT")

# now the defaultAssay is "integrated"
# if not scaled yet, do:
# combined.sct <- ScaleData(combined.sct)

combined.sct_v3 <- RunPCA(object = combined.sct_v3,
                       reduction.name = "integrated_pca")
combined.sct_v3 <- RunUMAP(combined.sct_v3,
                        dims = 1:50,
                        reduction = "integrated_pca",
                        reduction.name = "integrated_umap")

# Given a merged object with multiple SCT models, this function uses minimum of the median UMI (calculated using the raw UMI counts) of individual objects to reverse the individual SCT regression model using minimum of median UMI as the sequencing depth covariate. The counts slot of the SCT assay is replaced with recorrected counts and the data slot is replaced with log1p of recorrected counts.
combined.sct.consistent_v3 <- PrepSCTFindMarkers(combined.sct_v3,
                                              assay = 'SCT')

DimPlot(combined.sct.consistent_v3,
        label = TRUE,
        reduction = 'integrated_umap',
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v3: RNA integrated umap")
split and SCTransform (regress out unwanted variation)
split and SCTransform (regress out unwanted variation)

split and normalization (peaks assay)

DefaultAssay(mouse_lung_count_filter) <- "peaks"
DefaultAssay(mouse_lung_v3) <- "peaks"

# split
obj.list <- SplitObject(mouse_lung_v3, split.by = "sample")

# normalization of each
# make sure to keep peak counts > 0
atac.list <- lapply(X = obj.list, function(x){
    peak_keep = which(rowSums(x@assays$peaks@counts) > 0)
    CreateSeuratObject(x@assays$peaks@counts[peak_keep,],
                       meta.data = x@meta.data,
                       assay = 'peaks')   %>%
        FindTopFeatures(min.cutoff = "q5") %>%
        RunTFIDF() %>%
        RunSVD()
})



# integration
# find integration anchors
integration.anchors <- FindIntegrationAnchors(
  object.list = atac.list,
  reduction = "rlsi",
  anchor.features = rownames(atac.list$P5),
  dims = 2:50,
  n.trees = 30)

# integrate LSI embeddings
atac.integrated_v3 <- IntegrateEmbeddings(
                        anchorset = integration.anchors,
                        reductions = mouse_lung_count_filter[["lsi"]],
                        new.reduction.name = "integrated_lsi",
                        dims.to.integrate = 1:50)



atac.integrated_v3 <- RunUMAP(atac.integrated_v3,
                           reduction = 'integrated_lsi',
                           dims = 2:50,
                           reduction.name = "atac_integrated_umap")


DimPlot(atac.integrated_v3,
        reduction = "atac_integrated_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v3: peaks integrated umap")
split and normalization (peaks assay)
split and normalization (peaks assay)

add RNA “integrated assay + reduction” to mouse_lung_filter add peaks “integrated reduction” to mouse_lung_filter

Retain the dimensional reductions needed for the final analysis

# 這邊放入的 SCT 與 integrated 都是 normalize 後的 "data"
mouse_lung_v3[["SCT"]] <- CreateAssayObject(counts = GetAssayData(
                                                              object =  combined.sct.consistent_v3,
                                                              assay = "SCT",
                                                              slot = 'data'))
mouse_lung_v3[["integrated"]] <- CreateAssayObject(counts = GetAssayData(
                                                              object =  combined.sct.consistent_v3,
                                                              assay = "integrated",
                                                              slot = 'data'))

# 要把 "counts" 複製過來
mouse_lung_v3@assays$SCT@counts <- combined.sct.consistent_v3@assays$SCT@counts
mouse_lung_v3@assays$integrated@counts <- combined.sct.consistent_v3@assays$integrated@counts



mouse_lung_v3@reductions <- append(combined.sct.consistent_v3@reductions,
                                   atac.integrated_v3@reductions)





# 重新 normalize peaks assay (why???)
#DefaultAssay(mouse_lung_v3) <- "peaks"

#mouse_lung_v3 %>%
#        FindTopFeatures(min.cutoff = "q5") %>%
#        RunTFIDF() %>%
#        RunSVD()


integrated_multiome_v3 <- mouse_lung_v3

WNN

integrated_multiome_v3 <- FindMultiModalNeighbors(integrated_multiome_v3,
                                               reduction.list = list("integrated_pca",
                                                                     "integrated_lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v3 <- RunUMAP(integrated_multiome_v3,
                                nn.name = "weighted.nn",
                                reduction.name = "wnn_umap",
                                return.model=TRUE)
# res = 1
integrated_multiome_v3 <- FindClusters(integrated_multiome_v3,
                                    graph.name = "wsnn",
                                    algorithm = 3,
                                    verbose = FALSE,
                                    resolution = 1)

# WNN clustering
DimPlot(integrated_multiome_v3,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
ggtitle("v3: WNN clustering")

DimPlot(integrated_multiome_v3,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "wsnn_res.1") +
  ggtitle("v3: WNN clustering (res:1)")
WNN
WNN
WNN
WNN

v4 workflow (non-IntegrateData)

SCTransform without IntegrateData

# 把剛剛 seurat_phase計算的 s_genes與 g2m_genes資料加入到__中
mouse_lung_v4 <- mouse_lung_count_filter
mouse_lung_v4@meta.data <- seurat_phase_V3andV4_Regress@meta.data
DefaultAssay(mouse_lung_v4) <- "RNA"


# split object
split_seurat <- SplitObject(mouse_lung_v4, split.by = "sample")

# SCTransform n=16000 var features for each object
rna.list <- lapply(X = split_seurat, function(x){
   CreateSeuratObject(x@assays$RNA@counts, meta.data = x@meta.data) %>%
   SCTransform(vst.flavor="v2",
               vars.to.regress = c("S.Score", "G2M.Score", "percent.mt"),
               verbose = TRUE,
               ncells = 5000,
               variable.features.n = 16000)
})


my_select_features_v4 <- SelectIntegrationFeatures(rna.list,
                                                nfeatures = 16000,
                                                assay = c("SCT","SCT"),
                                                verbose = TRUE)

combined.sct.consistent_v4 <- PrepSCTFindMarkers(merge(rna.list$P5,
                                                       rna.list$P30),
                                                 assay = 'SCT')


DefaultAssay(combined.sct.consistent_v4) <- "SCT"
VariableFeatures(combined.sct.consistent_v4) <- my_select_features_v4

combined.sct.consistent_v4 <- RunPCA(object = combined.sct.consistent_v4,
                                reduction.name = "SCT_pca")

combined.sct.consistent_v4 <- RunUMAP(combined.sct.consistent_v4,
                                 dims = 1:25,
                                 reduction = "SCT_pca",
                                 reduction.name = "SCT_umap")

DimPlot(combined.sct.consistent_v4,
        label = TRUE,
        reduction = 'SCT_umap',
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v4: RNA non-integrated umap")
SCTransform without IntegrateData
SCTransform without IntegrateData

peaks

# split
obj.list <- SplitObject(mouse_lung_v4, split.by = "sample")

# normalization of each
# make sure to keep peak counts > 0
atac.list <- lapply(X = obj.list, function(x){

    peak_keep = which(rowSums(x@assays$peaks@counts) > 0)
    CreateSeuratObject(x@assays$peaks@counts[peak_keep,],
                       meta.data = x@meta.data,
                       assay = 'peaks')   %>%
        FindTopFeatures(min.cutoff = "q5") %>%
        RunTFIDF()
})

atac.integrated_v4 <- merge(atac.list$P5, atac.list$P30)
atac.integrated_v4 <- FindTopFeatures(atac.integrated_v4, min.cutoff = "q5")
atac.integrated_v4 <- RunSVD(atac.integrated_v4)
atac.integrated_v4 <- RunUMAP(atac.integrated_v4,
                           reduction = 'lsi',
                           dims = 2:50,
                           reduction.name = "peaks_umap")


DimPlot(atac.integrated_v4,
        reduction = "peaks_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
  ggtitle("v4: peaks non-integrated umap")
peaks
peaks

Combine all assays

integrated_multiome_v4 <- atac.integrated_v4


# move just the "data" slots!!!!!!
integrated_multiome_v4[["RNA"]]  <- CreateAssayObject(counts = GetAssayData(
                                                              object =  combined.sct.consistent_v4,
                                                              assay = "RNA",
                                                              slot =  "counts"))
integrated_multiome_v4[["SCT"]]  <- CreateAssayObject(counts = GetAssayData(
                                                              object =  combined.sct.consistent_v4,
                                                              assay = "SCT",
                                                              slot =  "data"))

# 所以這邊最後integrated_multiome裏面
# SCT assay 的 "counts" slot 其實顯示的數值就跟其 "data" slot 一樣

# 要再把 mouse_lung_filter_SCT 的 SCT assay counts slot 複製過來
# RNA assay 就維持原始的 "counts" slot
integrated_multiome_v4@assays$SCT@counts <- combined.sct.consistent_v4@assays$SCT@counts

integrated_multiome_v4@reductions <- append(integrated_multiome_v4@reductions,
                                            combined.sct.consistent_v4@reductions)

WNN analysis


integrated_multiome_v4 <- FindMultiModalNeighbors(integrated_multiome_v4,
                                               reduction.list = list("SCT_pca",
                                                                     "lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v4 <- RunUMAP(integrated_multiome_v4,
                                nn.name = "weighted.nn",
                                reduction.name = "wnn_umap",
                                return.model=TRUE)
# res = 1
integrated_multiome_v4 <- FindClusters(integrated_multiome_v4,
                                    graph.name = "wsnn",
                                    algorithm = 3,
                                    verbose = FALSE,
                                    resolution = 1)



# WNN clustering
DimPlot(integrated_multiome_v4,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "sample") +
ggtitle("v4: WNN clustering")

DimPlot(integrated_multiome_v4,
        reduction = "wnn_umap",
        label = TRUE,
        label.size = 2.5,
        repel = TRUE,
        group.by = "wsnn_res.1") +
  ggtitle("v4: WNN clustering (res:1)")
WNN analysis
WNN analysis
WNN analysis
WNN analysis

scType celltyping

database preprocess (https://doi.org/10.1242/dev.199512)

filter the database

Negretti <- read_csv("Negretti_mouse_lung_total.csv")
Negretti_filtered <- Negretti[,c(-1)]
Negretti_filtered$pct.diff <- abs(Negretti_filtered$pct.1 - Negretti_filtered$pct.2)



# only keep genes with p_val_adj <= 0.05
Negretti_filtered <- Negretti_filtered[Negretti_filtered$p_val_adj <= 0.05, ]

# only keep genes with pct diffrence >= 0.1
Negretti_filtered <- Negretti_filtered[Negretti_filtered$pct.diff >= 0.1, ]

# 32299 -> 26252 features

separate into positive and negative gene (20 each):

# positive gene list
Negretti_filtered_pos <- Negretti_filtered[Negretti_filtered$avg_log2FC > 0.25,]
Negretti_filtered_pos <- Negretti_filtered_pos[Negretti_filtered_pos$pct.1 > 0.5,]
Negretti_filtered_pos <- Negretti_filtered_pos[Negretti_filtered_pos$pct.2 < 0.5,]

Negretti_filtered_pos <- Negretti_filtered_pos %>%
                         group_by(alias) %>%
                         slice_max(order_by = avg_log2FC,
                                   n = min(table(Negretti_filtered_pos$alias)))
# 20 genes for each cell type






# negative gene
Negretti_filtered_neg <- Negretti_filtered[Negretti_filtered$avg_log2FC < -0.25,]
Negretti_filtered_neg <- Negretti_filtered_neg[Negretti_filtered_neg$pct.1 > 0.1,]
Negretti_filtered_neg <- Negretti_filtered_neg[Negretti_filtered_neg$pct.2 < 0.5,]

table(Negretti_filtered_neg$alias)

Negretti_filtered_neg <- Negretti_filtered_neg %>%
                         group_by(alias) %>%
                         slice_min(order_by = avg_log2FC,
                                   n = min(table(Negretti_filtered_neg$alias)))
# 12 genes for each cell type

reformat

library(unheadr)

Negretti_scTypeDB_pos <- Negretti_filtered_pos[,6:7] %>%
  unwrap_cols(groupingVar = alias, separator = ",")

Negretti_scTypeDB_neg <- Negretti_filtered_neg[,6:7] %>%
  unwrap_cols(groupingVar = alias, separator = ",")

Negretti_scTypeDB <-  merge(Negretti_scTypeDB_pos, Negretti_scTypeDB_neg, by='alias', all=TRUE)


colnames(Negretti_scTypeDB) = c("cellName","geneSymbolmore1","geneSymbolmore2")
Negretti_scTypeDB$tissueType <- "Lung"
Negretti_scTypeDB$shortName <- Negretti_scTypeDB$cellName

# 配合scType的finction,先儲存為.xlsx檔案
write.xlsx(Negretti_scTypeDB, file = "Negretti_scTypeDB.xlsx")

scType

db_ = "./Negretti_scTypeDB.xlsx"
tissue = "Lung"
gs_list = gene_sets_prepare(db_, tissue)
DefaultAssay(integrated_multiome_v1) <- "RNA"
DefaultAssay(integrated_multiome_v2) <- "RNA"
DefaultAssay(integrated_multiome_v3) <- "RNA"
DefaultAssay(integrated_multiome_v4) <- "RNA"



# we need the scale.data slot in assay
integrated_multiome_v1 <- ScaleData(object =  integrated_multiome_v1)

integrated_multiome_v2 <- NormalizeData(object =  integrated_multiome_v2)
integrated_multiome_v2 <- ScaleData(object =  integrated_multiome_v2)

integrated_multiome_v3 <- ScaleData(object =  integrated_multiome_v3)

integrated_multiome_v4 <- NormalizeData(object =  integrated_multiome_v4)
integrated_multiome_v4 <- ScaleData(object =  integrated_multiome_v4)



es.max_v1 = sctype_score(scRNAseqData = integrated_multiome_v1[["RNA"]]@scale.data,
                      scaled = TRUE,
                      gs = gs_list$gs_positive,
                      gs2 = gs_list$gs_negative)

es.max_v2 = sctype_score(scRNAseqData = integrated_multiome_v2[["RNA"]]@scale.data,
                      scaled = TRUE,
                      gs = gs_list$gs_positive,
                      gs2 = gs_list$gs_negative)

es.max_v3 = sctype_score(scRNAseqData = integrated_multiome_v3[["RNA"]]@scale.data,
                      scaled = TRUE,
                      gs = gs_list$gs_positive,
                      gs2 = gs_list$gs_negative)

es.max_v4 = sctype_score(scRNAseqData = integrated_multiome_v4[["RNA"]]@scale.data,
                      scaled = TRUE,
                      gs = gs_list$gs_positive,
                      gs2 = gs_list$gs_negative)

merge by cluster

# 要改res.XXX

# v1
cL_resutls_v1 = do.call("rbind",
                     lapply(unique(integrated_multiome_v1@meta.data$wsnn_res.1),
                            function(cl){es.max.cl = sort(
    rowSums(
      es.max_v1[ ,rownames(
        integrated_multiome_v1@meta.data[integrated_multiome_v1@meta.data$wsnn_res.1==cl, ])]),
        decreasing = !0)
    head(
      data.frame(
        cluster = cl,
        type = names(es.max.cl),
        scores = es.max.cl,
        ncells = sum(integrated_multiome_v1@meta.data$wsnn_res.1==cl)), 10)
}))

sctype_scores_v1 = cL_resutls_v1 %>% group_by(cluster) %>% top_n(n = 1, wt = scores)




# v2
cL_resutls_v2 = do.call("rbind",
                     lapply(unique(integrated_multiome_v2@meta.data$wsnn_res.1),
                            function(cl){es.max.cl = sort(
    rowSums(
      es.max_v2[ ,rownames(
        integrated_multiome_v2@meta.data[integrated_multiome_v2@meta.data$wsnn_res.1==cl, ])]),
        decreasing = !0)
    head(
      data.frame(
        cluster = cl,
        type = names(es.max.cl),
        scores = es.max.cl,
        ncells = sum(integrated_multiome_v2@meta.data$wsnn_res.1==cl)), 10)
}))

sctype_scores_v2 = cL_resutls_v2 %>% group_by(cluster) %>% top_n(n = 1, wt = scores)




# v3
cL_resutls_v3 = do.call("rbind",
                     lapply(unique(integrated_multiome_v3@meta.data$wsnn_res.1),
                            function(cl){es.max.cl = sort(
    rowSums(
      es.max_v3[ ,rownames(
        integrated_multiome_v3@meta.data[integrated_multiome_v3@meta.data$wsnn_res.1==cl, ])]),
        decreasing = !0)
    head(
      data.frame(
        cluster = cl,
        type = names(es.max.cl),
        scores = es.max.cl,
        ncells = sum(integrated_multiome_v3@meta.data$wsnn_res.1==cl)), 10)
}))

sctype_scores_v3 = cL_resutls_v3 %>% group_by(cluster) %>% top_n(n = 1, wt = scores)




# v4
cL_resutls_v4 = do.call("rbind",
                     lapply(unique(integrated_multiome_v4@meta.data$wsnn_res.1),
                            function(cl){es.max.cl = sort(
    rowSums(
      es.max_v4[ ,rownames(
        integrated_multiome_v4@meta.data[integrated_multiome_v4@meta.data$wsnn_res.1==cl, ])]),
        decreasing = !0)
    head(
      data.frame(
        cluster = cl,
        type = names(es.max.cl),
        scores = es.max.cl,
        ncells = sum(integrated_multiome_v4@meta.data$wsnn_res.1==cl)), 10)
}))

sctype_scores_v4 = cL_resutls_v4 %>% group_by(cluster) %>% top_n(n = 1, wt = scores)

set low-confident clusters (with ScType score < cell number/4 ) to “unknown”

sctype_scores_v1$type[as.numeric(as.character(sctype_scores_v1$scores)) < sctype_scores_v1$ncells/4] = "Unknown"

sctype_scores_v2$type[as.numeric(as.character(sctype_scores_v2$scores)) < sctype_scores_v2$ncells/4] = "Unknown"

sctype_scores_v3$type[as.numeric(as.character(sctype_scores_v3$scores)) < sctype_scores_v3$ncells/4] = "Unknown"

sctype_scores_v4$type[as.numeric(as.character(sctype_scores_v4$scores)) < sctype_scores_v4$ncells/4] = "Unknown"

Import the assigned cell types into the integrated_multiome Seurat object

integrated_multiome_v1$scType_Negretti_DB_RNA = ""
integrated_multiome_v2$scType_Negretti_DB_RNA = ""
integrated_multiome_v3$scType_Negretti_DB_RNA = ""
integrated_multiome_v4$scType_Negretti_DB_RNA = ""


# 要改integrated_snn_res.XXX
# v1
for(j in unique(sctype_scores_v1$cluster)){
  cl_type = sctype_scores_v1[sctype_scores_v1$cluster==j,]
  integrated_multiome_v1@meta.data$scType_Negretti_DB_RNA[integrated_multiome_v1@meta.data$wsnn_res.1 == j] = as.character(cl_type$type[1])
}

# 按照 Negretti paper 的方式排列 cell type,使 label 的排序與 Negretti 一致
Idents(integrated_multiome_v1) <- "scType_Negretti_DB_RNA"
integrated_multiome_v1@active.ident <- factor(integrated_multiome_v1@active.ident,
                            levels=c("Meso_Cardiomyocyte",
                                     "Meso_Smooth_Muscle",
                                     "Meso_Mesothelium",
                                     "Meso_Pericyte",
                                     "Meso_Adventitial_FB",
                                     "Meso_Myofibroblast",
                                     "Meso_Prolif_Myo_FB",
                                     "Meso_Wnt2_FB",
                                     "Meso_Prolif_Wnt2_FB",
                                     "Endo_Lymphatic",
                                     "Endo_aCap",
                                     "Endo_gCap",
                                     "Endo_Prolif_gCap",
                                     "Endo_Venous_maEC",
                                     "Endo_Arterial_maEC",
                                     "Epi_Neuroendocrine",
                                     "Epi_Secretory",
                                     "Epi_Cilliated",
                                     "Epi_Mki67_AT2",
                                     "Epi_AT2",
                                     "Epi_AT1",
                                     "Epi_Transitional",
                                     "Epi_EarlyEpithelium",
                                     "Unknown"))




# v2
for(j in unique(sctype_scores_v2$cluster)){
  cl_type = sctype_scores_v2[sctype_scores_v2$cluster==j,]
  integrated_multiome_v2@meta.data$scType_Negretti_DB_RNA[integrated_multiome_v2@meta.data$wsnn_res.1 == j] = as.character(cl_type$type[1])
}

# 按照 Negretti paper 的方式排列 cell type,使 label 的排序與 Negretti 一致
Idents(integrated_multiome_v2) <- "scType_Negretti_DB_RNA"
integrated_multiome_v2@active.ident <- factor(integrated_multiome_v2@active.ident,
                            levels=c("Meso_Cardiomyocyte",
                                     "Meso_Smooth_Muscle",
                                     "Meso_Mesothelium",
                                     "Meso_Pericyte",
                                     "Meso_Adventitial_FB",
                                     "Meso_Myofibroblast",
                                     "Meso_Prolif_Myo_FB",
                                     "Meso_Wnt2_FB",
                                     "Meso_Prolif_Wnt2_FB",
                                     "Endo_Lymphatic",
                                     "Endo_aCap",
                                     "Endo_gCap",
                                     "Endo_Prolif_gCap",
                                     "Endo_Venous_maEC",
                                     "Endo_Arterial_maEC",
                                     "Epi_Neuroendocrine",
                                     "Epi_Secretory",
                                     "Epi_Cilliated",
                                     "Epi_Mki67_AT2",
                                     "Epi_AT2",
                                     "Epi_AT1",
                                     "Epi_Transitional",
                                     "Epi_EarlyEpithelium",
                                     "Unknown"))



# v3
for(j in unique(sctype_scores_v3$cluster)){
  cl_type = sctype_scores_v3[sctype_scores_v3$cluster==j,]
  integrated_multiome_v3@meta.data$scType_Negretti_DB_RNA[integrated_multiome_v3@meta.data$wsnn_res.1 == j] = as.character(cl_type$type[1])
}

# 按照 Negretti paper 的方式排列 cell type,使 label 的排序與 Negretti 一致
Idents(integrated_multiome_v3) <- "scType_Negretti_DB_RNA"
integrated_multiome_v3@active.ident <- factor(integrated_multiome_v3@active.ident,
                            levels=c("Meso_Cardiomyocyte",
                                     "Meso_Smooth_Muscle",
                                     "Meso_Mesothelium",
                                     "Meso_Pericyte",
                                     "Meso_Adventitial_FB",
                                     "Meso_Myofibroblast",
                                     "Meso_Prolif_Myo_FB",
                                     "Meso_Wnt2_FB",
                                     "Meso_Prolif_Wnt2_FB",
                                     "Endo_Lymphatic",
                                     "Endo_aCap",
                                     "Endo_gCap",
                                     "Endo_Prolif_gCap",
                                     "Endo_Venous_maEC",
                                     "Endo_Arterial_maEC",
                                     "Epi_Neuroendocrine",
                                     "Epi_Secretory",
                                     "Epi_Cilliated",
                                     "Epi_Mki67_AT2",
                                     "Epi_AT2",
                                     "Epi_AT1",
                                     "Epi_Transitional",
                                     "Epi_EarlyEpithelium",
                                     "Unknown"))



# v4
for(j in unique(sctype_scores_v4$cluster)){
  cl_type = sctype_scores_v4[sctype_scores_v4$cluster==j,]
  integrated_multiome_v4@meta.data$scType_Negretti_DB_RNA[integrated_multiome_v4@meta.data$wsnn_res.1 == j] = as.character(cl_type$type[1])
}

# 按照 Negretti paper 的方式排列 cell type,使 label 的排序與 Negretti 一致
Idents(integrated_multiome_v4) <- "scType_Negretti_DB_RNA"
integrated_multiome_v4@active.ident <- factor(integrated_multiome_v4@active.ident,
                            levels=c("Meso_Cardiomyocyte",
                                     "Meso_Smooth_Muscle",
                                     "Meso_Mesothelium",
                                     "Meso_Pericyte",
                                     "Meso_Adventitial_FB",
                                     "Meso_Myofibroblast",
                                     "Meso_Prolif_Myo_FB",
                                     "Meso_Wnt2_FB",
                                     "Meso_Prolif_Wnt2_FB",
                                     "Endo_Lymphatic",
                                     "Endo_aCap",
                                     "Endo_gCap",
                                     "Endo_Prolif_gCap",
                                     "Endo_Venous_maEC",
                                     "Endo_Arterial_maEC",
                                     "Epi_Neuroendocrine",
                                     "Epi_Secretory",
                                     "Epi_Cilliated",
                                     "Epi_Mki67_AT2",
                                     "Epi_AT2",
                                     "Epi_AT1",
                                     "Epi_Transitional",
                                     "Epi_EarlyEpithelium",
                                     "Unknown"))






# assign a new column "celltype" (epithelium, endothelium and mesenchyme)
library(stringr)

# v1
integrated_multiome_v1$celltype <- integrated_multiome_v1$scType_Negretti_DB_RNA
integrated_multiome_v1$celltype[which(str_detect(integrated_multiome_v1$celltype, "^Epi_"))] <-
"Epithelium"
integrated_multiome_v1$celltype[which(str_detect(integrated_multiome_v1$celltype, "^Endo_"))] <- "Endothelium"
integrated_multiome_v1$celltype[which(str_detect(integrated_multiome_v1$celltype, "^Meso_"))] <- "Mesenchyme"


# v2
integrated_multiome_v2$celltype <- integrated_multiome_v2$scType_Negretti_DB_RNA
integrated_multiome_v2$celltype[which(str_detect(integrated_multiome_v2$celltype, "^Epi_"))] <-
"Epithelium"
integrated_multiome_v2$celltype[which(str_detect(integrated_multiome_v2$celltype, "^Endo_"))] <- "Endothelium"
integrated_multiome_v2$celltype[which(str_detect(integrated_multiome_v2$celltype, "^Meso_"))] <- "Mesenchyme"


# v3
integrated_multiome_v3$celltype <- integrated_multiome_v3$scType_Negretti_DB_RNA
integrated_multiome_v3$celltype[which(str_detect(integrated_multiome_v3$celltype, "^Epi_"))] <-
"Epithelium"
integrated_multiome_v3$celltype[which(str_detect(integrated_multiome_v3$celltype, "^Endo_"))] <- "Endothelium"
integrated_multiome_v3$celltype[which(str_detect(integrated_multiome_v3$celltype, "^Meso_"))] <- "Mesenchyme"


# v4
integrated_multiome_v4$celltype <- integrated_multiome_v4$scType_Negretti_DB_RNA
integrated_multiome_v4$celltype[which(str_detect(integrated_multiome_v4$celltype, "^Epi_"))] <-
"Epithelium"
integrated_multiome_v4$celltype[which(str_detect(integrated_multiome_v4$celltype, "^Endo_"))] <- "Endothelium"
integrated_multiome_v4$celltype[which(str_detect(integrated_multiome_v4$celltype, "^Meso_"))] <- "Mesenchyme"

Visualization

pdf(file = "scType_RNAassay_result_v1.pdf", height = 8, width = 10)
DimPlot(integrated_multiome_v1,
        reduction = "wnn_umap",
        label = TRUE,
        repel = TRUE,
        group.by = "celltype") +
  ggtitle("v1: Celltyping results of scType (use RNA assay)")
dev.off()


pdf(file = "scType_RNAassay_result_v2.pdf", height = 8, width = 10)
DimPlot(integrated_multiome_v2,
        reduction = "wnn_umap",
        label = TRUE,
        repel = TRUE,
        group.by = "celltype") +
  ggtitle("v2: Celltyping results of scType (use RNA assay)")
dev.off()

pdf(file = "scType_RNAassay_result_v3.pdf", height = 8, width = 10)
DimPlot(integrated_multiome_v3,
        reduction = "wnn_umap",
        label = TRUE,
        repel = TRUE,
        group.by = "celltype") +
  ggtitle("v3: Celltyping results of scType (use RNA assay)")
dev.off()

pdf(file = "scType_RNAassay_result_v4.pdf", height = 8, width = 10)
DimPlot(integrated_multiome_v4,
        reduction = "wnn_umap",
        label = TRUE,
        repel = TRUE,
        group.by = "celltype") +
  ggtitle("v4: Celltyping results of scType (use RNA assay)")
dev.off()
Visualization
Visualization
Visualization
Visualization
Visualization
Visualization
Visualization
Visualization

Comparison

library(ggvenn)
df_v1 <- as.data.frame(integrated_multiome_v1$celltype)
df_v2 <- as.data.frame(integrated_multiome_v2$celltype)
df_v3 <- as.data.frame(integrated_multiome_v3$celltype)
df_v4 <- as.data.frame(integrated_multiome_v4$celltype)


df_v1$cells <- rownames(df_v1)
df_v2$cells <- rownames(df_v2)
df_v3$cells <- rownames(df_v3)
df_v4$cells <- rownames(df_v4)


A <-list("v1" = df_v1$cells,
         "v2" = df_v2$cells,
         "v3" = df_v3$cells,
         "v4" = df_v4$cells)

# create venn diagram and display all the sets
ggvenn(A)
Comparison
Comparison

Cell IDs depend mainly on whether cellranger aggr is used: v1/v2 share their cells, while v3/v4 share theirs

Do cells found only in v1/v2 or v3/v4 visibly affect UMAP clustering?


#put all data frames into list
df_list <- list(df_v1, df_v2, df_v3, df_v4)

#merge all data frames together
df_merge <- Reduce(function(x, y) merge(x, y, all=TRUE), df_list)



df_merge[is.na(df_merge)] <- c("FilteredOut")

colnames(df_merge) <- c("cells","v1","v2","v3","v4")

df_merge <- df_merge[,-1]

library(ggsankey)
df_merge <- df_merge %>%
  make_long(v1,v2,v3,v4)




pl <- ggplot(df_merge, aes(x = x,
                     next_x = next_x,
                     node = node,
                     next_node = next_node,
                     fill = factor(node)))

pl <- pl +geom_sankey(flow.alpha = 0.5,          #This Creates the transparency of your node
                      node.color = "black",     # This is your node color
                      show.legend = TRUE)        # This determines if you want your legend to show

pl
Do cells found only in v1/v2 or v3/v4 visibly affect UMAP clustering?
Do cells found only in v1/v2 or v3/v4 visibly affect UMAP clustering?

FilterOut indicates that the cell does not exist in that workflow.

Subset endothelial cells and redraw UMAP to examine developmental changes across samples

integrated_multiome_v1_endo <- subset(integrated_multiome_v1, 
                                           subset = celltype == "Endothelium")


integrated_multiome_v1_endo <- FindMultiModalNeighbors(integrated_multiome_v1_endo, 
                                               reduction.list = list("integrated_pca",
                                                                     "integrated_lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v1_endo <- RunUMAP(integrated_multiome_v1_endo, 
                                nn.name = "weighted.nn", 
                                reduction.name = "wnn_umap", 
                                return.model=TRUE)



########
integrated_multiome_v2_endo <- subset(integrated_multiome_v2, 
                                           subset = celltype == "Endothelium")
integrated_multiome_v2_endo <- FindMultiModalNeighbors(integrated_multiome_v2_endo, 
                                               reduction.list = list("SCT_pca",
                                                                     "lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v2_endo <- RunUMAP(integrated_multiome_v2_endo, 
                                nn.name = "weighted.nn", 
                                reduction.name = "wnn_umap", 
                                return.model=TRUE)

#######
integrated_multiome_v3_endo <- subset(integrated_multiome_v3, 
                                           subset = celltype == "Endothelium")


integrated_multiome_v3_endo <- FindMultiModalNeighbors(integrated_multiome_v3_endo, 
                                               reduction.list = list("integrated_pca",
                                                                     "integrated_lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v3_endo <- RunUMAP(integrated_multiome_v3_endo, 
                                nn.name = "weighted.nn", 
                                reduction.name = "wnn_umap", 
                                return.model=TRUE)







########
integrated_multiome_v4_endo <- subset(integrated_multiome_v4, 
                                           subset = celltype == "Endothelium")
integrated_multiome_v4_endo <- FindMultiModalNeighbors(integrated_multiome_v4_endo, 
                                               reduction.list = list("SCT_pca",
                                                                     "lsi"),
                                               dims.list = list(1:50, 2:50),
                                               k.nn = 100)

integrated_multiome_v4_endo <- RunUMAP(integrated_multiome_v4_endo, 
                                nn.name = "weighted.nn", 
                                reduction.name = "wnn_umap", 
                                return.model=TRUE)





##########

DimPlot(integrated_multiome_v1_endo, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "sample") + 
  ggtitle("v1: endothelium")

DimPlot(integrated_multiome_v2_endo, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "sample") + 
  ggtitle("v2: endothelium")

DimPlot(integrated_multiome_v3_endo, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "sample") + 
  ggtitle("v3: endothelium")

DimPlot(integrated_multiome_v4_endo, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "sample") + 
  ggtitle("v4: endothelium")
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples
Subset endothelial cells and redraw UMAP to examine developmental changes across samples

Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP

df_merge_noNA <- Reduce(function(x, y) merge(x, y, all=F), df_list)   # 8597


# 移除非 consensus 的細胞
uni <- df_merge_noNA[,-1] %>%
    rowwise() %>%
    do(data.frame(., Unique = n_distinct(unlist(.)))) %>% select(Unique)

df_merge_noNA$Unique <- uni$Unique
df_merge_noNA <- df_merge_noNA[df_merge_noNA$Unique == 1,] # 6141

Concensus_cell_ID <- df_merge_noNA$cells

integrated_multiome_v1_consensus <- subset(integrated_multiome_v1, 
                                           subset = cells %in% Concensus_cell_ID)
integrated_multiome_v2_consensus <- subset(integrated_multiome_v2, 
                                           subset = cells %in% Concensus_cell_ID)
integrated_multiome_v3_consensus <- subset(integrated_multiome_v3, 
                                           subset = cells %in% Concensus_cell_ID)
integrated_multiome_v4_consensus <- subset(integrated_multiome_v4, 
                                           subset = cells %in% Concensus_cell_ID)


DimPlot(integrated_multiome_v1_consensus, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "celltype") + 
  ggtitle("v1-only consensus:\n Celltyping results of scType (use RNA assay)")


DimPlot(integrated_multiome_v2_consensus, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "celltype") + 
  ggtitle("v2-only consensus:\n Celltyping results of scType (use RNA assay)")


DimPlot(integrated_multiome_v3_consensus, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "celltype") + 
  ggtitle("v3-only consensus:\n Celltyping results of scType (use RNA assay)")


DimPlot(integrated_multiome_v4_consensus, 
        reduction = "wnn_umap", 
        label = TRUE, 
        repel = TRUE,
        group.by = "celltype") + 
  ggtitle("v4-only consensus:\n Celltyping results of scType (use RNA assay)")
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP
Retain consensus cells assigned to the same cell type in v1–v4, then display only those cells in each workflow’s UMAP

Inspecting only consensus cells still did not make it clear which workflow was preferable.

← Back to projects