In this tutorial, we demonstrate how to perform vertical integrative clustering (iCluster) analysis of single cell RNA-seq and ATAC-seq data using the iCluster2b function, which implements an updated iCluster method originally reported by Shen, Wang and Mo. 2023. We use a paired scRNA-seq and scATAC-seq data measured for 10,412 PBMCs for iCluster analysis. The paired data are publicly available on the 10x website, which include the following files.
The paired data are used by Seurat to illustrate the Weighted Nearest Neighbor (WNN) method for integrative clustering of single cell multi-omics data. We will follow the tutorial WNN Analysis to process the paired scRNA-seq and scATAC-seq data.
library(iClusterPlus)
library(lattice)
library(gplots)
library(Seurat)
library(SeuratData)
library(cowplot)
library(dplyr)
library(Rphenograph)
library(umap)
library(mclust)
library(MatrixGenerics)
library(Matrix)
library(EnsDb.Hsapiens.v86)
library(ggplot2)
library(GenomeInfoDb) #standardChromosomes
library(Signac) #v1.16.0
library(Azimuth)
library(Silhouette)
library(cluster)
library(knitr)
The iCluster analysis of single cell multi-omics data can be carried out in the following 4 steps.
We follow the Seurat’s WNN Analysis tutorial to process the scRNA-seq and scATAC-seq data. The processing workflow includes filtering, normalization, feature selection, scaling and dimension reduction for each dataset.
# The following are Seurat's codes to process the scRNA-seq and scATACT-seq data
# read scRNA-seq and scATAC-seq data from the data folder of working directory
inputdata.10x <- Read10X_h5("../pbmc_data/pbmc_granulocyte_sorted_10k_filtered_feature_bc_matrix.h5")
# extract RNA and ATAC data
rna_counts <- inputdata.10x$`Gene Expression`
atac_counts <- inputdata.10x$Peaks
# Create Seurat object
pbmc <- CreateSeuratObject(counts = rna_counts)
pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-")
# Add in the ATAC-seq data and only use peaks in standard chromosomes
grange.counts <- StringToGRanges(rownames(atac_counts), sep = c(":", "-"))
grange.use <- seqnames(grange.counts) %in% standardChromosomes(grange.counts)
atac_counts <- atac_counts[as.vector(grange.use), ]
annotations <- GetGRangesFromEnsDb(ensdb = EnsDb.Hsapiens.v86)
seqlevelsStyle(annotations) <- 'UCSC'
genome(annotations) <- "hg38"
# read ATAC Per fragment information file in the data folder of working directory
frag.file <- "../pbmc_data/pbmc_granulocyte_sorted_10k_atac_fragments.tsv.gz"
# create chromosome assay
chrom_assay <- CreateChromatinAssay(
counts = atac_counts,
sep = c(":", "-"),
genome = 'hg38',
fragments = frag.file,
min.cells = 10,
annotation = annotations
)
pbmc[["ATAC"]] <- chrom_assay
#basic QC based on the number of detected molecules for RNA, ATAC and mitochondrial percentage.
#VlnPlot(pbmc,features=c("nCount_RNA", "nCount_ATAC", "percent.mt"), ncol=3,log=TRUE,pt.size = 0) + NoLegend()
pbmc <- subset(
x = pbmc,
subset = nCount_ATAC < 7e4 &
nCount_ATAC > 5e3 &
nCount_RNA < 25000 &
nCount_RNA > 1000 &
percent.mt < 20
)
# RNA analysis
DefaultAssay(pbmc) <- "RNA"
options(future.globals.maxSize= 850*1024^2) #calculate the size for an 850mb limit:
pbmc <- SCTransform(pbmc, verbose = FALSE) %>% RunPCA() %>% RunUMAP(dims = 1:50, reduction.name = 'umap.rna', reduction.key = 'rnaUMAP_')
# ATAC analysis
# Seurat excludes the first dimension as this is typically correlated with sequencing depth
DefaultAssay(pbmc) <- "ATAC"
pbmc <- RunTFIDF(pbmc)
pbmc <- FindTopFeatures(pbmc, min.cutoff = 'q0')
pbmc <- RunSVD(pbmc) #reduction.name = "lsi
pbmc <- RunUMAP(pbmc, reduction = 'lsi', dims = 2:50, reduction.name = "umap.atac", reduction.key = "atacUMAP_")
# cell annotation using Azimuth package
DefaultAssay(pbmc) <- "RNA"
pbmc <- RunAzimuth(pbmc, reference = "pbmcref")
The iCluster modeling generates a latent factor matrix (meanZ), which captures the major sources of variation of the multi-omics data (scRNA-seq and scATAC-seq). As a result, the latent factor matrix can be used for sample clustering and visualization.
# Select the top 20% most variable regions and merge the neighboring regions with gap width <=10000 bps
atac <- mergeRegion(peak.ct=pbmc[["ATAC"]]$data,rm.prob=0.8,rm.isolate=FALSE,min.gapwidth=10000)
dim(atac)
## [1] 15441 10412
# we use the normalized and scaled RNA-seq data (top 3000 genes) and top 10% most variable ATAC-seq features for iCluster analysis
dim(pbmc[['SCT']]$scale.data)
## [1] 3000 10412
pbmcList <- list(RNA=t(pbmc[['SCT']]$scale.data),ATAC=t(as.matrix(atac)))
rm(atac)
# PCA variance plot
pcaVarPlot(pbmcList,K=100)
From the variance plot, we can see that the explained variance starts to level off around the 10th PC. For iCluster modeling of single cell multi-omics data, we suggest selecting the number PCs based on the point at which the explained variance levels off. In general, using the first 10 to 20 PCs is sufficient to distinguish major cell types. Using higher-numbered PCs (e.g., 40-50) may help identify rare cell populations and capture more subtle heterogeneity. Here, we select K=50 as the number of latent factors for iCluster modeling.
# since features have been selected, we set lambda to a small value to minimize feature selection
date()
## [1] "Thu Nov 5 23:15:05 2026"
fit2 = iCluster2b(xList=pbmcList,K=50,lambda=list(0.1,0.1),method=c("lasso","lasso"))
date()
## [1] "Thu Nov 5 23:16:32 2026"
We use the Louvain method implemented in the Rphenograph package to perform cell clustering analysis. Then, we project the cells to a 2-dimensional space using UMAP for visualization.
## clustering of cells using Louvain method and the latent factor matrix generated by iCluster
ic.graph <- Rphenograph(fit2$meanZ, k=30)
## Finding nearest neighbors...DONE ~ 3.395 s
## Compute jaccard coefficient between nearest-neighbor sets...DONE ~ 1.392 s
## Build undirected graph from the weighted links...DONE ~ 0.278 s
## Run louvain clustering on the graph ...DONE ~ 0.414 s
## Return a community class
## -Modularity value: 0.8725663
## -Number of clusters: 20
tabclst <- table(membership(ic.graph[[2]]))
## order the clusters based on cluster size
clstlevels <- as.numeric(names(tabclst)[order(tabclst,decreasing = TRUE)])
pbmc.iClusters <- factor(membership(ic.graph[[2]]),levels=clstlevels,labels=1:length(clstlevels))
names(pbmc.iClusters) <- rownames(pbmcList$RNA)
# Projecting cells to 2-dimensional space using UMAP
ic.umap <- umap(fit2$meanZ)
rownames(ic.umap$layout) <- rownames(pbmcList$RNA)
colnames(ic.umap$layout) <- c("umap1","umap2")
## put umap layout and cluster IDs into the Seurat object bm
pbmc[["ic.umap"]] <- CreateDimReducObject(embeddings = ic.umap$layout, key = "icumap_")
pbmc$iClusters <- pbmc.iClusters
We use Seurat’s function DimPlot to visualize the cells on a 2-dimensional UMAP space.
ic.p1 <- DimPlot(pbmc,reduction="ic.umap",group.by="iClusters",label=TRUE,label.size=4,repel=TRUE) +
NoLegend() + ggtitle("iClusters") + labs(x="UMAP_1",y="UMAP_2")
ic.p2 <- DimPlot(pbmc, reduction="ic.umap",group.by="predicted.celltype.l2",label=TRUE,label.size=4, repel=TRUE) +
NoLegend() + ggtitle("Cell types") + labs(x="UMAP_1",y="UMAP_2")
ic.p1 + ic.p2
col.scheme <- alist()
col.scheme[[1]] <- bluered(256)
col.scheme[[2]] <- bluered(256)
fit2$clusters <- pbmc$iClusters
ic.hm <- iClusterPlus::plotHeatmap(fit=fit2,xList=pbmcList,type=c("gaussian","gaussian"),
threshold=c(0.10, 0.10),feature.order=c(T,T),feature.scale=c(T,T),
dist.method = "euclidean", hclust.method="ward.D",col.scheme = col.scheme,width=10,
sparse=c(T,T),cap=c(0.99,0.99))
For comparison, we perform integrative clustering analysis using Seurat’s WNN method. For more details of WNN analysis, we refer users to the Seurat’s tutorial (Weighted Nearest Neighbor Analysis).
pbmc <- FindMultiModalNeighbors(pbmc, reduction.list = list("pca", "lsi"), dims.list = list(1:50, 2:50))
pbmc <- RunUMAP(pbmc, nn.name = "weighted.nn", reduction.name = "wnn.umap", reduction.key = "wnnUMAP_")
pbmc <- FindClusters(pbmc, graph.name = "wsnn", algorithm = 3, verbose = FALSE)
We visualize the cell clusters generated by Seurat WNN analysis, alongside cell annotations
p3 <- DimPlot(pbmc, reduction="wnn.umap",group.by="seurat_clusters", label=TRUE,label.size=4,repel=TRUE) +
NoLegend() + ggtitle("Seurat_clusters")
p4 <- DimPlot(pbmc, reduction="wnn.umap",group.by="predicted.celltype.l2",label=TRUE,label.size=4,repel=TRUE) +
NoLegend() + ggtitle("Cell types")
p3 + p4
Finally, we compare the integrative clustering results of iCluster and Seurat WNN using normalized mutual information (NMI), adjusted rand index (ARI) and average silhouette width (ASW). In general, higher index values indicate better clustering performance.
# comparison using normalized mutual information (NMI)
compare(pbmc$predicted.celltype.l2, pbmc$iClusters, method = "nmi")
## [1] 0.7623989
compare(pbmc$predicted.celltype.l2, pbmc$seurat_clusters, method = "nmi")
## [1] 0.7315697
# Comparison using adjusted rand index
compare(pbmc$predicted.celltype.l2, pbmc$iClusters, method = "adjusted.rand")
## [1] 0.6155965
compare(pbmc$predicted.celltype.l2, pbmc$seurat_clusters, method = "adjusted.rand")
## [1] 0.596371
# Comparison using average silhouette width
sil.ic <- silhouette(as.numeric(pbmc$iClusters), dist(Embeddings(pbmc, reduction = "ic.umap")))
summary(sil.ic)$avg.width
## [1] 0.428286
sil.wnn <- silhouette(as.numeric(pbmc$seurat_clusters), dist(Embeddings(pbmc, reduction = "wnn.umap")))
summary(sil.wnn)$avg.width
## [1] 0.4177851
Table of cell types vs. iClusters
# table of annotated cell types and iClusters
icTable <- table(pbmc$predicted.celltype.l2,pbmc$iClusters)
knitr::kable(icTable)
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| B intermediate | 1 | 1 | 3 | 1 | 0 | 0 | 346 | 0 | 0 | 0 | 25 | 10 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| B memory | 0 | 1 | 0 | 0 | 0 | 0 | 105 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| B naive | 2 | 0 | 1 | 0 | 0 | 0 | 14 | 0 | 0 | 0 | 318 | 16 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| CD14 Mono | 2123 | 3 | 0 | 2 | 1 | 559 | 1 | 1 | 31 | 0 | 0 | 280 | 46 | 1 | 1 | 0 | 0 | 0 | 1 | 0 |
| CD16 Mono | 11 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 370 | 0 | 0 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| CD4 Naive | 0 | 731 | 0 | 18 | 0 | 0 | 0 | 0 | 0 | 9 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| CD4 Proliferating | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 5 | 0 |
| CD4 TCM | 0 | 660 | 1343 | 47 | 8 | 0 | 0 | 1 | 0 | 8 | 1 | 7 | 1 | 40 | 2 | 0 | 4 | 0 | 1 | 0 |
| CD4 TEM | 0 | 0 | 10 | 0 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| CD8 Naive | 0 | 20 | 1 | 1000 | 17 | 0 | 0 | 2 | 0 | 358 | 1 | 0 | 0 | 0 | 0 | 0 | 3 | 0 | 0 | 0 |
| CD8 TCM | 0 | 2 | 23 | 11 | 87 | 0 | 0 | 0 | 0 | 4 | 0 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| CD8 TEM | 0 | 1 | 5 | 1 | 530 | 0 | 0 | 19 | 0 | 1 | 0 | 7 | 0 | 2 | 1 | 0 | 32 | 0 | 0 | 0 |
| cDC1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 6 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| cDC2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 124 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| dnT | 0 | 0 | 6 | 2 | 2 | 0 | 0 | 0 | 0 | 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
| gdT | 0 | 4 | 0 | 1 | 69 | 0 | 0 | 9 | 0 | 1 | 0 | 1 | 0 | 0 | 5 | 0 | 12 | 0 | 0 | 0 |
| HSPC | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 25 | 0 | 0 |
| ILC | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| MAIT | 0 | 0 | 5 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0 | 105 | 0 | 0 | 0 | 0 | 0 |
| NK | 1 | 0 | 0 | 0 | 36 | 0 | 2 | 380 | 0 | 0 | 0 | 7 | 0 | 0 | 2 | 0 | 0 | 0 | 0 | 0 |
| NK Proliferating | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 3 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 10 | 0 |
| NK_CD56bright | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 22 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| pDC | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 106 | 0 | 0 | 0 | 0 |
| Plasmablast | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 18 |
| Treg | 0 | 3 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 116 | 0 | 0 | 1 | 0 | 0 | 0 |
sessionInfo()
## R version 4.5.2 (2025-10-31)
## Platform: aarch64-apple-darwin20
## Running under: macOS Sequoia 15.8.1
##
## Matrix products: default
## BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
## LAPACK: /Library/Frameworks/R.framework/Versions/4.5-arm64/Resources/lib/libRlapack.dylib; LAPACK version 3.12.1
##
## 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: America/New_York
## tzcode source: internal
##
## attached base packages:
## [1] stats4 parallel stats graphics grDevices utils datasets
## [8] methods base
##
## other attached packages:
## [1] future_1.75.0 knitr_1.51
## [3] cluster_2.1.8.3 Silhouette_0.9.6
## [5] Azimuth_0.5.0 shinyBS_0.65.0
## [7] Signac_1.16.0 GenomeInfoDb_1.46.2
## [9] EnsDb.Hsapiens.v86_2.99.0 ensembldb_2.34.0
## [11] AnnotationFilter_1.34.0 GenomicFeatures_1.62.0
## [13] AnnotationDbi_1.72.0 Biobase_2.70.0
## [15] GenomicRanges_1.62.1 Seqinfo_1.0.0
## [17] IRanges_2.44.0 S4Vectors_0.48.1
## [19] BiocGenerics_0.56.0 generics_0.1.4
## [21] MatrixGenerics_1.22.0 matrixStats_1.5.0
## [23] mclust_6.1.3 umap_0.2.10.0
## [25] Rphenograph_0.99.1 igraph_2.3.3
## [27] ggplot2_4.0.3 dplyr_1.2.1
## [29] cowplot_1.2.0 pbmcsca.SeuratData_3.0.0
## [31] pbmcref.SeuratData_1.0.0 bmcite.SeuratData_0.3.0
## [33] SeuratData_0.2.2.9002 Seurat_5.5.1
## [35] SeuratObject_5.4.0 sp_2.2-3
## [37] gplots_3.3.0 lattice_0.22-9
## [39] iClusterPlus_1.49.1 irlba_2.3.7
## [41] Matrix_1.7-6
##
## loaded via a namespace (and not attached):
## [1] fs_2.1.0 ProtGenerics_1.42.0
## [3] spatstat.sparse_3.2-0 bitops_1.1-0
## [5] DirichletMultinomial_1.52.0 TFBSTools_1.48.0
## [7] httr_1.4.8 RColorBrewer_1.1-3
## [9] backports_1.5.1 tools_4.5.2
## [11] sctransform_0.4.3 R6_2.6.1
## [13] DT_0.34.0 lazyeval_0.2.3
## [15] uwot_0.2.4 rhdf5filters_1.22.0
## [17] withr_3.0.3 gridExtra_2.3.1
## [19] progressr_1.0.0 cli_3.6.6
## [21] spatstat.explore_3.8-2 fastDummies_1.7.6
## [23] shinyjs_2.1.1 labeling_0.4.3
## [25] sass_0.4.10 S7_0.2.2
## [27] spatstat.data_3.1-9 ggridges_0.5.7
## [29] pbapply_1.7-4 askpass_1.2.1
## [31] Rsamtools_2.26.0 foreign_0.8-91
## [33] dichromat_2.0-1 parallelly_1.48.0
## [35] BSgenome_1.78.0 rstudioapi_0.19.0
## [37] RSQLite_3.53.3 BiocIO_1.20.0
## [39] gtools_3.9.5 ica_1.0-3
## [41] spatstat.random_3.5-1 car_3.1-5
## [43] googlesheets4_1.1.2 abind_1.4-8
## [45] lifecycle_1.0.5 yaml_2.3.12
## [47] carData_3.0-6 SummarizedExperiment_1.40.0
## [49] glmGamPoi_1.22.0 rhdf5_2.54.1
## [51] SparseArray_1.10.10 Rtsne_0.17
## [53] grid_4.5.2 blob_1.3.0
## [55] promises_1.5.0 shinydashboard_0.7.3
## [57] crayon_1.5.3 pwalign_1.6.0
## [59] miniUI_0.1.2 beachmat_2.26.0
## [61] cigarillo_1.0.0 KEGGREST_1.50.0
## [63] pillar_1.11.1 rjson_0.2.23
## [65] future.apply_1.20.2 codetools_0.2-20
## [67] fastmatch_1.1-8 glue_1.8.1
## [69] spatstat.univar_3.2-0 data.table_1.18.4
## [71] vctrs_0.7.3 png_0.1-9
## [73] spam_2.11-4 cellranger_1.1.0
## [75] gtable_0.3.6 cachem_1.1.0
## [77] xfun_0.60 S4Arrays_1.10.1
## [79] mime_0.13 survival_3.8-9
## [81] gargle_1.6.1 RcppRoll_0.3.2
## [83] fitdistrplus_1.2-6 ROCR_1.0-12
## [85] nlme_3.1-170 bit64_4.8.2
## [87] RcppAnnoy_0.0.23 bslib_0.12.0
## [89] rpart_4.1.27 KernSmooth_2.23-26
## [91] otel_0.2.0 colorspace_2.1-3
## [93] Hmisc_5.2-6 SeuratDisk_0.0.0.9021
## [95] seqLogo_1.76.0 DBI_1.3.0
## [97] nnet_7.3-21 tidyselect_1.2.1
## [99] bit_4.6.0 compiler_4.5.2
## [101] curl_7.1.0 htmlTable_2.5.0
## [103] hdf5r_1.3.12 DelayedArray_0.36.1
## [105] plotly_4.12.1 rtracklayer_1.70.1
## [107] checkmate_2.3.4 scales_1.4.0
## [109] caTools_1.18.4 lmtest_0.9-40
## [111] rappdirs_0.3.4 stringr_1.6.0
## [113] digest_0.6.39 goftest_1.2-3
## [115] presto_1.0.0 spatstat.utils_3.2-4
## [117] rmarkdown_2.31 XVector_0.50.0
## [119] base64enc_0.1-6 htmltools_0.5.9
## [121] pkgconfig_2.0.3 sparseMatrixStats_1.22.0
## [123] fastmap_1.2.0 rlang_1.3.0
## [125] htmlwidgets_1.6.4 UCSC.utils_1.6.1
## [127] DelayedMatrixStats_1.32.0 shiny_1.14.0
## [129] farver_2.1.2 jquerylib_0.1.4
## [131] zoo_1.9-0 jsonlite_2.0.0
## [133] BiocParallel_1.44.0 VariantAnnotation_1.56.0
## [135] RCurl_1.98-1.19 magrittr_2.0.5
## [137] Formula_1.2-6 dotCall64_1.2
## [139] patchwork_1.3.2 Rhdf5lib_1.32.0
## [141] Rcpp_1.1.2 reticulate_1.46.0
## [143] stringi_1.8.9 MASS_7.3-66
## [145] plyr_1.8.9 listenv_1.0.0
## [147] ggrepel_0.9.8 deldir_2.0-4
## [149] Biostrings_2.78.0 splines_4.5.2
## [151] tensor_1.5.1 BSgenome.Hsapiens.UCSC.hg38_1.4.5
## [153] ggpubr_1.0.0 spatstat.geom_3.8-2
## [155] ggsignif_0.6.4 RcppHNSW_0.7.0
## [157] reshape2_1.4.5 TFMPvalue_1.0.0
## [159] XML_3.99-0.23 evaluate_1.0.5
## [161] biovizBase_1.58.0 JASPAR2020_0.99.10
## [163] httpuv_1.6.17 RANN_2.6.2
## [165] tidyr_1.3.2 openssl_2.4.2
## [167] purrr_1.2.2 polyclip_1.10-7
## [169] scattermore_1.2 broom_1.0.13
## [171] xtable_1.8-8 restfulr_0.0.17
## [173] RSpectra_0.16-2 rstatix_1.1.0
## [175] later_1.4.8 googledrive_2.1.2
## [177] viridisLite_0.4.3 tibble_3.3.1
## [179] memoise_2.0.1 GenomicAlignments_1.46.0
## [181] globals_0.19.1