In this vignette we will analyse a single-cell co-assay dataset measuring gene expression and DNA accessibility in the same cells. This vignette is similar to the PBMC multiomic vignette, but demonstrates a similar joint analysis in a different species and with data gathered using a different technology.

This dataset was published by Chen, Lake, and Zhang (2019) and uses a technology called SNARE-seq. We will look at a dataset from the adult mouse brain, and the raw data can be downloaded from NCBI GEO here: https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE126074

As the fragment files for this dataset are not publicly available we have re-mapped the raw data to the mm10 genome and created a fragment file using Sinto.

The fragment file can be downloaded here: https://signac-objects.s3.amazonaws.com/snareseq/fragments.sort.bed.gz

The fragment file index can be downloaded here: https://signac-objects.s3.amazonaws.com/snareseq/fragments.sort.bed.gz.tbi

Code used to create the fragment file from raw data is available here: https://github.com/timoast/SNARE-seq

Data loading

First we create a Seurat object containing two different assays, one containing the gene expression data and one containing the DNA accessibility data.

To load the count data, we can use the Read10X() function from Seurat by first placing the barcodes.tsv.gz, matrix.mtx.gz, and features.tsv.gz files into a separate folder.

library(Signac)
library(Seurat)
library(ggplot2)
library(EnsDb.Mmusculus.v79)

# load processed data matrices for each assay
rna <- Read10X("GSE126074_AdBrainCortex_rna/", gene.column = 1)
atac <- Read10X("GSE126074_AdBrainCortex_atac/", gene.column = 1)
fragments <- "fragments.sort.bed.gz"

# create a Seurat object and add the assays
snare <- CreateSeuratObject(counts = rna)
snare[['ATAC']] <- CreateChromatinAssay(
  counts = atac,
  sep = c(":", "-"),
  genome = "mm10",
  fragments = fragments
)

# extract gene annotations from EnsDb
annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Mmusculus.v79)

# change to UCSC style since the data was mapped to mm10
seqlevels(annotations) <- paste0('chr', seqlevels(annotations))
genome(annotations) <- "mm10"

# add the gene information to the object
Annotation(snare[["ATAC"]]) <- annotations

Quality control

DefaultAssay(snare) <- "ATAC"
snare <- TSSEnrichment(snare)
snare <- NucleosomeSignal(snare)
snare$blacklist_fraction <- FractionCountsInRegion(
  object = snare,
  assay = 'ATAC',
  regions = blacklist_mm10
)
Idents(snare) <- "all"  # group all cells together, rather than by replicate
VlnPlot(
  snare,
  features = c("nCount_RNA", "nCount_ATAC", "TSS.enrichment",
               "nucleosome_signal", "blacklist_fraction"),
  pt.size = 0.1,
  ncol = 5
)

snare <- subset(
  x = snare,
  subset = blacklist_fraction < 0.03 &
    TSS.enrichment < 20 &
    nCount_RNA > 800 &
    nCount_ATAC > 500
)
snare
## An object of class Seurat 
## 277704 features across 8055 samples within 2 assays 
## Active assay: ATAC (244544 features, 0 variable features)
##  2 layers present: counts, data
##  1 other assay present: RNA

Gene expression data processing

Process gene expression data using Seurat

DefaultAssay(snare) <- "RNA"

snare <- FindVariableFeatures(snare, nfeatures = 3000)
snare <- NormalizeData(snare)
snare <- ScaleData(snare)
snare <- RunPCA(snare, npcs = 30)
snare <- RunUMAP(snare, dims = 1:30, reduction.name = "umap.rna")
snare <- FindNeighbors(snare, dims = 1:30)
snare <- FindClusters(snare, resolution = 0.5, algorithm = 3)
## Modularity Optimizer version 1.3.0 by Ludo Waltman and Nees Jan van Eck
## 
## Number of nodes: 8055
## Number of edges: 324240
## 
## Running smart local moving algorithm...
## Maximum modularity in 10 random starts: 0.8900
## Number of communities: 14
## Elapsed time: 4 seconds
p1 <- DimPlot(snare, label = TRUE) + NoLegend() + ggtitle("RNA UMAP")

DNA accessibility data processing

Process the DNA accessibility data using Signac

DefaultAssay(snare) <- 'ATAC'

snare <- FindTopFeatures(snare, min.cutoff = 10)
snare <- RunTFIDF(snare)
snare <- RunSVD(snare)
snare <- RunUMAP(snare, reduction = 'lsi', dims = 2:30, reduction.name = 'umap.atac')
p2 <- DimPlot(snare, reduction = 'umap.atac', label = TRUE) + NoLegend() + ggtitle("ATAC UMAP")
p1 + p2

Integration with scRNA-seq data

Next we can annotate cell types in the dataset by transferring labels from an existing scRNA-seq dataset for the adult mouse brain, produced by the Allen Institute.

You can download the raw data for this experiment from the Allen Institute website, and view the code used to construct this object on GitHub. Alternatively, you can download the pre-processed Seurat object here.

# label transfer from Allen brain
allen <- readRDS("allen_brain.rds")
allen <- UpdateSeuratObject(allen)

# use the RNA assay in the SNARE-seq data for integration with scRNA-seq
DefaultAssay(snare) <- 'RNA'

transfer.anchors <- FindTransferAnchors(
  reference = allen,
  query = snare,
  dims = 1:30,
  reduction = 'cca'
)

predicted.labels <- TransferData(
  anchorset = transfer.anchors,
  refdata = allen$subclass,
  weight.reduction = snare[['pca']],
  dims = 1:30
)

snare <- AddMetaData(object = snare, metadata = predicted.labels)
# label clusters based on predicted ID
new.cluster.ids <- c(
  "L2/3 IT",
  "L4",
  "L6 IT",
  "L5 CT",
  "L4",
  "L5 PT",
  "Pvalb",
  "Sst",
  "Astro",
  "Oligo",
  "Vip/Lamp5",
  "L6 IT.2",
  "L6b",
  "NP"
)
names(x = new.cluster.ids) <- levels(x = snare)
snare <- RenameIdents(object = snare, new.cluster.ids)
snare$celltype <- Idents(snare)
DimPlot(snare, group.by = 'celltype', label = TRUE, reduction = 'umap.rna')

Jointly visualizing gene expression and DNA accessibility

We can visualize both the gene expression and DNA accessibility information at the same time using the CoveragePlot() function. This makes it easy to compare DNA accessibility in a given region for different cell types and overlay gene expression information for different genes.

DefaultAssay(snare) <- "ATAC"
CoveragePlot(snare, region = "chr2-22620000-22660000", features = "Gad2")

Session Info
## R version 4.3.1 (2023-06-16)
## Platform: aarch64-apple-darwin20 (64-bit)
## Running under: macOS Sonoma 14.5
## 
## Matrix products: default
## BLAS:   /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRblas.0.dylib 
## LAPACK: /Library/Frameworks/R.framework/Versions/4.3-arm64/Resources/lib/libRlapack.dylib;  LAPACK version 3.11.0
## 
## locale:
## [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8
## 
## time zone: Asia/Singapore
## tzcode source: internal
## 
## attached base packages:
## [1] stats4    stats     graphics  grDevices utils     datasets  methods  
## [8] base     
## 
## other attached packages:
##  [1] EnsDb.Mmusculus.v79_2.99.0 ensembldb_2.26.0          
##  [3] AnnotationFilter_1.26.0    GenomicFeatures_1.54.4    
##  [5] AnnotationDbi_1.64.1       Biobase_2.62.0            
##  [7] GenomicRanges_1.54.1       GenomeInfoDb_1.38.8       
##  [9] IRanges_2.36.0             S4Vectors_0.40.2          
## [11] BiocGenerics_0.48.1        ggplot2_3.5.1             
## [13] Seurat_5.1.0               SeuratObject_5.0.2        
## [15] sp_2.1-4                   Signac_1.14.0             
## 
## loaded via a namespace (and not attached):
##   [1] fs_1.6.4                    ProtGenerics_1.34.0        
##   [3] matrixStats_1.3.0           spatstat.sparse_3.0-3      
##   [5] bitops_1.0-8                httr_1.4.7                 
##   [7] RColorBrewer_1.1-3          tools_4.3.1                
##   [9] sctransform_0.4.1           backports_1.5.0            
##  [11] utf8_1.2.4                  R6_2.5.1                   
##  [13] lazyeval_0.2.2              uwot_0.1.16                
##  [15] withr_3.0.1                 prettyunits_1.2.0          
##  [17] gridExtra_2.3               progressr_0.14.0           
##  [19] cli_3.6.3                   textshaping_0.4.0          
##  [21] spatstat.explore_3.2-7      fastDummies_1.7.3          
##  [23] labeling_0.4.3              sass_0.4.9                 
##  [25] spatstat.data_3.0-4         ggridges_0.5.6             
##  [27] pbapply_1.7-2               pkgdown_2.0.9              
##  [29] Rsamtools_2.18.0            systemfonts_1.1.0          
##  [31] foreign_0.8-86              R.utils_2.12.3             
##  [33] dichromat_2.0-0.1           parallelly_1.38.0          
##  [35] BSgenome_1.70.2             rstudioapi_0.16.0          
##  [37] RSQLite_2.3.7               generics_0.1.3             
##  [39] BiocIO_1.12.0               ica_1.0-3                  
##  [41] spatstat.random_3.2-3       dplyr_1.1.4                
##  [43] Matrix_1.6-5                ggbeeswarm_0.7.2           
##  [45] fansi_1.0.6                 abind_1.4-5                
##  [47] R.methodsS3_1.8.2           lifecycle_1.0.4            
##  [49] yaml_2.3.10                 SummarizedExperiment_1.32.0
##  [51] SparseArray_1.2.4           BiocFileCache_2.10.2       
##  [53] Rtsne_0.17                  grid_4.3.1                 
##  [55] blob_1.2.4                  promises_1.3.0             
##  [57] crayon_1.5.3                miniUI_0.1.1.1             
##  [59] lattice_0.22-6              cowplot_1.1.3              
##  [61] KEGGREST_1.42.0             pillar_1.9.0               
##  [63] knitr_1.48                  rjson_0.2.21               
##  [65] future.apply_1.11.2         codetools_0.2-19           
##  [67] fastmatch_1.1-4             leiden_0.4.3.1             
##  [69] glue_1.7.0                  data.table_1.15.4          
##  [71] vctrs_0.6.5                 png_0.1-8                  
##  [73] spam_2.10-0                 gtable_0.3.5               
##  [75] cachem_1.1.0                xfun_0.47                  
##  [77] S4Arrays_1.2.1              mime_0.12                  
##  [79] survival_3.6-4              RcppRoll_0.3.1             
##  [81] fitdistrplus_1.1-11         ROCR_1.0-11                
##  [83] nlme_3.1-164                bit64_4.0.5                
##  [85] progress_1.2.3              filelock_1.0.3             
##  [87] RcppAnnoy_0.0.22            bslib_0.8.0                
##  [89] irlba_2.3.5.1               vipor_0.4.7                
##  [91] KernSmooth_2.23-24          rpart_4.1.23               
##  [93] colorspace_2.1-1            DBI_1.2.3                  
##  [95] Hmisc_5.1-3                 nnet_7.3-19                
##  [97] ggrastr_1.0.2               tidyselect_1.2.1           
##  [99] bit_4.0.5                   compiler_4.3.1             
## [101] curl_5.2.1                  htmlTable_2.4.3            
## [103] xml2_1.3.6                  desc_1.4.3                 
## [105] DelayedArray_0.28.0         plotly_4.10.4              
## [107] rtracklayer_1.62.0          checkmate_2.3.2            
## [109] scales_1.3.0                lmtest_0.9-40              
## [111] rappdirs_0.3.3              stringr_1.5.1              
## [113] digest_0.6.37               goftest_1.2-3              
## [115] spatstat.utils_3.0-4        rmarkdown_2.28             
## [117] XVector_0.42.0              htmltools_0.5.8.1          
## [119] pkgconfig_2.0.3             base64enc_0.1-3            
## [121] MatrixGenerics_1.14.0       highr_0.11                 
## [123] dbplyr_2.5.0                fastmap_1.2.0              
## [125] rlang_1.1.4                 htmlwidgets_1.6.4          
## [127] shiny_1.9.1                 farver_2.1.2               
## [129] jquerylib_0.1.4             zoo_1.8-12                 
## [131] jsonlite_1.8.8              BiocParallel_1.36.0        
## [133] R.oo_1.26.0                 VariantAnnotation_1.48.1   
## [135] RCurl_1.98-1.16             magrittr_2.0.3             
## [137] Formula_1.2-5               GenomeInfoDbData_1.2.11    
## [139] dotCall64_1.1-1             patchwork_1.2.0            
## [141] munsell_0.5.1               Rcpp_1.0.13                
## [143] reticulate_1.37.0           stringi_1.8.4              
## [145] zlibbioc_1.48.2             MASS_7.3-60.0.1            
## [147] plyr_1.8.9                  parallel_4.3.1             
## [149] listenv_0.9.1               ggrepel_0.9.5              
## [151] deldir_2.0-4                Biostrings_2.70.3          
## [153] splines_4.3.1               tensor_1.5                 
## [155] hms_1.1.3                   igraph_2.0.3               
## [157] spatstat.geom_3.2-9         RcppHNSW_0.6.0             
## [159] reshape2_1.4.4              biomaRt_2.58.2             
## [161] XML_3.99-0.17               evaluate_0.24.0            
## [163] biovizBase_1.50.0           httpuv_1.6.15              
## [165] RANN_2.6.1                  tidyr_1.3.1                
## [167] purrr_1.0.2                 polyclip_1.10-6            
## [169] future_1.34.0               scattermore_1.2            
## [171] xtable_1.8-4                restfulr_0.0.15            
## [173] RSpectra_0.16-2             later_1.3.2                
## [175] viridisLite_0.4.2           ragg_1.3.2                 
## [177] tibble_3.2.1                beeswarm_0.4.0             
## [179] memoise_2.0.1               GenomicAlignments_1.38.2   
## [181] cluster_2.1.6               globals_0.16.3