Quality control of sc/snRNA-seq
Mariano Ruz Jurado
Goethe UniversitySource:
vignettes/DOtools.Rmd
DOtools.Rmd
Installation
DOtools is an R package distributed as part of the Bioconductor project. To install the package, start R and enter:
install.packages("BiocManager") # WORK iN PROGRESS
BiocManager::install("DOtools")
Alternatively, you can instead install the latest development version from GitHub with:
install.packages("devtools")
devtools::install_github("MarianoRuzJurado/DOtools")
Usage
DOtools contains different functions for processing and visualizing gene expression in scRNA/snRNA experiments:
In this vignette we showcase how to use the functions with public available data.
Libraries
DOtools can be imported as:
Quality control
DOtools
The DO.Import()
function provides a streamlined pipeline
for performing quality control on single-cell or single-nucleus RNA
sequencing (sc/snRNA-seq) data. It takes as input a list of .h5 files
generated by e.g. CellRanger or STARsolo, along with sample names and
metadata.
During preprocessing, low-quality genes and cells are filtered out based on specified thresholds. Genes expressed in fewer than five cells are removed. Cells are filtered according to mitochondrial gene content, number of detected genes, total UMI counts, and potential doublets. The function supports doublet detection using scDblFinder. Thresholds for mitochondrial content (e.g., 5% for scRNA-seq and 3% for snRNA-seq), gene counts, and UMI counts can be defined to tailor the filtering.
After filtering, samples are merged into one Seurat or SingleCellExperiment object, followed by log-normalisation, scaling, and the identification of highly variable genes. To help assess the effect of quality control, violin plots showing distributions of key metrics before and after filtering are automatically generated and saved alongside the input files. A summary of removed genes and cells is also recorded.
To show how the quality control works, we are going to use a public dataset from 10X from human blood of healthy and donors with a malignant tumor:
base <- DOtools:::.example_10x()
paths = c(file.path(base, "healthy/outs/filtered_feature_bc_matrix.h5"),
file.path(base, "disease/outs/filtered_feature_bc_matrix.h5"))
SCE_obj <- DO.Import(pathways = paths,
ids = c("healthy-1", "disease-1"),
DeleteDoublets = TRUE,
cut_mt = .05,
min_counts = 500,
min_genes = 300,
high_quantile = .95,
Seurat=FALSE) # Set to TRUE for Seurat object
We can now check the quality before introducing filterings:
prefilterplots <- system.file("figures", "prefilterplots-1.png", package = "DOtools")
pQC1 <- magick::image_read(prefilterplots)
plot(pQC1)
And after:
postfilterplots <- system.file("figures", "postfilterplots-1.png", package = "DOtools")
pQC2 <- magick::image_read(postfilterplots)
plot(pQC2)
We observed that most cells were removed due to increased mitochondrial
content. Depending on the experimental design, the mitochondrial content
threshold can be adjusted to retain a higher number of cells, if
minimizing cell loss is of relevance.
The DOtools package provides a slim object of this data set.
Please feel free, to use the one created from DO.Import for prettier
results or this slim downed version. We can observe how similar the
samples are through running a correlation analysis.
#Making sure we have a save folder
base <- tempfile("my_tempdir_")
dir.create(base)
SCE_obj <- readRDS(system.file("extdata", "sce_data.rds", package = "DOtools"))
DO.Correlation(SCE_obj)
#> Warning: `PackageCheck()` was deprecated in SeuratObject 5.0.0.
#> ℹ Please use `rlang::check_installed()` instead.
#> ℹ The deprecated feature was likely used in the Seurat package.
#> Please report the issue at <https://github.com/satijalab/seurat/issues>.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
#> Warning: The `slot` argument of `SetAssayData()` is deprecated as of SeuratObject 5.0.0.
#> ℹ Please use the `layer` argument instead.
#> ℹ The deprecated feature was likely used in the Seurat package.
#> Please report the issue at <https://github.com/satijalab/seurat/issues>.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
#> generated.
#> Scale for fill is already present.
#> Adding another scale for fill, which will replace the existing scale.
Data integration
After quality control the prefered integration method can be chosen
within Seurat’s IntegrateLayers
function. Additionally, we
implemented a new wrapper function for the scVI integration from the scvi-tools package.
After the integration completes, we run the Leiden algorithm to find
clusters and generate UMAP embeddings.
### ADDITIONAL STEPS FOR SCE OBJECTS, THESE STEPS WILL BE PERFORMED AUTOMATICALLY FOR SEURAT OBJECTS IN DO.IMPORT
### SKIP IF YOU USE SEURAT OBJECT FROM DO.IMPORT()
Seu_obj <- as.Seurat(SCE_obj)
Seu_obj[["RNA"]] <- split(Seu_obj[["RNA"]], f = Seu_obj$orig.ident)
Seu_obj <- FindVariableFeatures(Seu_obj)
#> Finding variable features for layer counts.healthy-1
#> Finding variable features for layer counts.disease-1
Seu_obj <- ScaleData(object = Seu_obj)
#> Centering and scaling data matrix
Seu_obj <- RunPCA(Seu_obj, verbose = FALSE, reduction.name = "PCA")
Seu_obj <- JoinLayers(Seu_obj)
Seu_obj[["RNA"]] <- split(Seu_obj[["RNA"]], f = Seu_obj$orig.ident)
#> Splitting 'counts', 'data' layers. Not splitting 'scale.data'. If you would like to split other layers, set in `layers` argument.
#####
#Integration through Seurat
Seu_obj <- IntegrateLayers(object = Seu_obj,
method = CCAIntegration,
orig.reduction = "PCA",
new.reduction = "INTEGRATED.CCA",
verbose = TRUE)
#> Finding all pairwise anchors
#> Running CCA
#> Merging objects
#> Finding neighborhoods
#> Finding anchors
#> Found 2607 anchors
#> Merging dataset 2 into 1
#> Extracting anchors for merged samples
#> Finding integration vectors
#> Finding integration vector weights
#> Integrating data
#After Integration we join the layers
Seu_obj <- JoinLayers(Seu_obj)
#(Optional) convert back to SCE object if you prefer that data class
SCE_obj <- as.SingleCellExperiment(Seu_obj)
#(Optional) Integration with scVI-Model
Seu_obj <- DO.scVI(sce_object = Seu_obj,
batch_key ="orig.ident",
layer_counts = "counts",
layer_logcounts = "logcounts")
After the integration finished, both corrected expression matrices can be found saved in the Seurat object and can be used for cluster calculations and UMAP projections. In this case, we will continue with Seuratv5 CCA Integration method.
Seu_obj <- FindNeighbors(object = Seu_obj, reduction = "INTEGRATED.CCA", dims = 1:50) #change dims accordingly
#> Computing nearest neighbor graph
#> Computing SNN
Seu_obj <- FindClusters(Seu_obj, resolution = 0.3, algorithm = 4, random.seed = 1234)
Seu_obj <- RunUMAP(object = Seu_obj, reduction = "INTEGRATED.CCA", reduction.name = "UMAP", dims = 1:50)
#> 09:25:09 UMAP embedding parameters a = 0.9922 b = 1.112
#> 09:25:09 Read 2807 rows and found 50 numeric columns
#> 09:25:09 Using Annoy for neighbor search, n_neighbors = 30
#> 09:25:09 Building Annoy index with metric = cosine, n_trees = 50
#> 0% 10 20 30 40 50 60 70 80 90 100%
#> [----|----|----|----|----|----|----|----|----|----|
#> **************************************************|
#> 09:25:09 Writing NN index file to temp file /tmp/RtmpPZHS4j/file1bb22659b45e3
#> 09:25:09 Searching Annoy index using 1 thread, search_k = 3000
#> 09:25:10 Annoy recall = 100%
#> 09:25:10 Commencing smooth kNN distance calibration using 1 thread with target n_neighbors = 30
#> 09:25:11 Initializing from normalized Laplacian + noise (using RSpectra)
#> 09:25:11 Commencing optimization for 500 epochs, with 130642 positive edges
#> 09:25:11 Using rng type: pcg
#> 09:25:14 Optimization finished
DO.UMAP(Seu_obj, group.by = "seurat_clusters")
DO.UMAP(Seu_obj, group.by = "condition", legend.position = "right", label = FALSE)
Semi-automatic annotation with Celltypist
Next up, we implemented a wrapper around the semi-automatic
annotation tool celltypist. It
will annotate the defined clusters based on the
Adult_COVID19_PBMC.pkl
model.
Seu_obj <- DO.CellTypist(Seu_obj,
modelName = "Healthy_COVID19_PBMC.pkl",
runCelltypistUpdate=TRUE,
over_clustering = "seurat_clusters")
#> 2025-07-26 09:25:15 - Running celltypist using model: Healthy_COVID19_PBMC.pkl
#> 2025-07-26 09:25:15 - Saving celltypist results to temporary folder: /tmp/RtmpPZHS4j/file1bb227d358eee
#> 2025-07-26 09:25:44 - Creating probality plot
DO.UMAP(Seu_obj, group.by = "autoAnnot", legend.position = "right")
The semi-automatic annotation is a good estimate of the cell types in
your object. But you should always manually validate the findings of the
model. You can manually define a set of marker genes for the cell
population or check the most preeminent genes per cluster by using
Seurat’s FindAllMarkers
function.
#pick top 5 per cluster
annotation_Markers <- FindAllMarkers(object = Seu_obj,
assay = "RNA",
group.by = "autoAnnot",
min.pct = 0.25,
logfc.threshold = 0.25)
#> Calculating cluster CD83_CD14_mono
#> Calculating cluster CD4.Naive
#> Calculating cluster CD8.Naive
#> Calculating cluster NK_16hi
#> Calculating cluster CD8.EM
#> Calculating cluster B_naive
#> Calculating cluster pDC
annotation_Markers <- annotation_Markers %>%
arrange(desc(avg_log2FC)) %>%
distinct(gene, .keep_all = TRUE) %>%
group_by(cluster) %>%
slice_head(n = 5)
p1 <- DO.Dotplot(sce_object = Seu_obj,
Feature = annotation_Markers,
group.by.x = "seurat_clusters",
plot.margin = c(1,1,1,1),
annotation_x = TRUE,
point_stroke = 0.1,
annotation_x_rev = TRUE,
textSize = 14,
hjust = 0.5,
vjust = 0,
textRot = 0,
segWidth = 0.3,
lwd = 3)
#> Scale for size is already present.
#> Adding another scale for size, which will replace the existing scale.
#manual set of markers
annotation_Markers <- data.frame(cluster = c("ImmuneCells",
rep("B_cells", 3),
rep("T_cells",3),
rep("NK", 2),
rep("Myeloid",3),
rep("pDC",3)),
genes = c("PTPRC", "CD79A", "BANK1", "MS4A1", "CD3E", "CD4", "IL7R", "NKG7",
"KLRD1","CD68", "CD14","ITGAM", "LILRA4", "CLEC4C", "LRRC26"))
p2 <- DO.Dotplot(sce_object = Seu_obj,
Feature = annotation_Markers,
group.by.x = "seurat_clusters",
plot.margin = c(1,1,1,1),
annotation_x = TRUE,
point_stroke = 0.1,
annotation_x_rev = TRUE,
textSize = 14,
hjust = 0.5,
vjust = 0,
textRot = 0,
segWidth = 0.3,
lwd = 3)
#> Scale for size is already present.
#> Adding another scale for size, which will replace the existing scale.
The manual markers for the immune cells show an agreement for the annotation therefore we can continue with it after some minor adjustments
Seu_obj$annotation <- plyr::revalue(Seu_obj$seurat_clusters, c(`1` = "T_cells",
`2` = "T_cells",
`3` = "NK",
`4` = "B_cells",
`5` = "Monocytes",
`6` = "NK",
`7` = "T_cells",
`8` = "pDC"))
DO.UMAP(Seu_obj, group.by = "annotation", legend.position = "right")
Cell composition
After the identification of the celltype populations, we can also evaluate if there are significant changes in these populations in the healthy and diseased condition using a wrapper function around the python tool scanpro.
DO.CellComposition(Seu_obj,
assay_normalized = "RNA",
cluster_column = "annotation",
sample_column = "orig.ident",
condition_column = "condition",
transform_method = "arcsin",
n_reps = 3)
#> 2025-07-26 09:25:48 - Bootstrapping method activated with 3 simulated replicates!
#> .
#> Using orig.ident, condition as id variables
#> Using condition as id variables
Reclustering of cell populations
Subpopulations can be tricky to find, therefore it is always a good practice to perform a reclustering of a given cell populations, if we are interested in a specific set of cells in a population. Here for example in the T cells. We will identify the subpopulations and then markers defining them.
Seu_obj <- DO.FullRecluster(Seu_obj, over_clustering = "annotation")
DO.UMAP(Seu_obj, group.by = "annotation_recluster")
T_cells <- DO.Subset(Seu_obj,
ident = "annotation_recluster",
ident_name = grep("T_cells", unique(Seu_obj$annotation_recluster), value = TRUE))
#> 2025-07-26 09:26:04 - Specified 'ident_name': expecting a categorical variable.
T_markers <- FindAllMarkers(T_cells, group.by = "annotation_recluster")
#> Calculating cluster T_cells_1
#> Calculating cluster T_cells_3
#> Calculating cluster T_cells_2
T_cells <- DO.CellTypist(T_cells,
modelName = "Healthy_COVID19_PBMC.pkl",
runCelltypistUpdate=FALSE,
over_clustering = "annotation_recluster",
SeuV5 = FALSE)
#> 2025-07-26 09:26:05 - Running celltypist using model: Healthy_COVID19_PBMC.pkl
#> 2025-07-26 09:26:05 - Saving celltypist results to temporary folder: /tmp/RtmpPZHS4j/file1bb227e62b879
#> 2025-07-26 09:26:17 - Creating probality plot
T_cells$annotation <- plyr::revalue(T_cells$annotation_recluster, c(`T_cells_1` = "CD4_T_cells",
`T_cells_2` = "CD4_T_cells",
`T_cells_3` = "CD4_T_cells",
`T_cells_4` = "CD8_T_cells"))
#> The following `from` values were not present in `x`: T_cells_4
Now that we identified the marker genes describing the different T cell populations. We can re-annotate them based on their expression profile and a new prediciton from Celltypist. After this we, can easily transfer the labels in the subset to the original object.
Seu_obj <- DO.TransferLabel(Seu_obj,
Subset_obj = T_cells,
annotation_column = "annotation",
subset_annotation = "annotation")
DO.UMAP(Seu_obj, group.by = "annotation", legend.position = "right")
Gene ontology analysis
To explore which biological processes are enriched in a specific cell type across conditions, we can perform gene ontology analysis. We’ll start by identifying differentially expressed genes, focusing here on T cells. For differential gene expression analysis, we introduced a new function, which combines DGE analysis using a single cell approach, e.g. the popular Wilcoxon test and a pseudobulk testing using DESeq2. We can then observe the results in a combined dataframe.
# this data set contains only one sample per condition we introduce replicates for showing the pseudo bulk approach
set.seed(123)
Seu_obj$orig.ident2 <- sample(rep(c("A", "B", "C", "D", "E", "F"), length.out = ncol(Seu_obj)))
CD4T_cells <- DO.Subset(Seu_obj, ident = "annotation", ident_name = "CD4_T_cells")
#> 2025-07-26 09:26:18 - Specified 'ident_name': expecting a categorical variable.
DGE_result <- DO.MultiDGE(CD4T_cells,
sample_col = "orig.ident2",
method_sc = "wilcox",
ident_ctrl = "healthy")
#> Names of identity class contain underscores ('_'), replacing with dashes ('-')
#> Centering and scaling data matrix
#>
#> This message is displayed once every 8 hours.
#> 2025-07-26 09:26:19 - Corrected annotation names in pseudo-bulk object by replacing '-' with '_'.
#> 2025-07-26 09:26:19 - Starting DGE single cell method analysis
#> 2025-07-26 09:26:19 - Comparing disease with healthy in: CD4_T_cells
#> 2025-07-26 09:26:19 - Finished DGE single cell method analysis
#> 2025-07-26 09:26:19 - Starting DGE pseudo bulk method analysis
#> 2025-07-26 09:26:19 - Comparing disease with healthy in: CD4_T_cells
#> converting counts to integer mode
#> gene-wise dispersion estimates
#> mean-dispersion relationship
#> final dispersion estimates
#> 2025-07-26 09:26:20 - Finished DGE pseudo bulk method analysis
head(DGE_result,10) %>%
kable(format = "html", table.attr = "style='width:100%;'") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
gene | pct.1 | pct.2 | celltype | condition | avg_log2FC_PB_DESeq2 | avg_log2FC_SC_wilcox | p_val_adj_PB_DESeq2 | p_val_adj_SC_wilcox | p_val_PB_DESeq2 | p_val_SC_wilcox |
---|---|---|---|---|---|---|---|---|---|---|
RGS1 | 0.847 | 0.053 | CD4_T_cells | disease | 5.725615 | 6.390029 | 0 | 0 | 0 | 0 |
SRGN | 0.985 | 0.481 | CD4_T_cells | disease | 3.713146 | 4.318726 | 0 | 0 | 0 | 0 |
ZFP36 | 0.908 | 0.419 | CD4_T_cells | disease | 2.921135 | 3.460342 | 0 | 0 | 0 | 0 |
KLF6 | 0.913 | 0.415 | CD4_T_cells | disease | 2.163426 | 2.734643 | 0 | 0 | 0 | 0 |
FOS | 0.939 | 0.583 | CD4_T_cells | disease | 2.338456 | 2.944901 | 0 | 0 | 0 | 0 |
RGCC | 0.810 | 0.326 | CD4_T_cells | disease | 2.686536 | 3.148416 | 0 | 0 | 0 | 0 |
DUSP2 | 0.767 | 0.235 | CD4_T_cells | disease | 2.895376 | 3.457257 | 0 | 0 | 0 | 0 |
DUSP1 | 0.937 | 0.595 | CD4_T_cells | disease | 1.560897 | 2.150082 | 0 | 0 | 0 | 0 |
ACTB | 0.985 | 0.999 | CD4_T_cells | disease | -1.948105 | -1.475069 | 0 | 0 | 0 | 0 |
LMNA | 0.497 | 0.049 | CD4_T_cells | disease | 3.789865 | 4.570318 | 0 | 0 | 0 | 0 |
After inspecting the DGE analysis, we continue with
DO.enrichR
function, which uses the enrichR API to run gene
set enrichment. It separates the DE genes into up- and down-regulated
sets and runs the analysis for each group independently
result_GO <- DO.enrichR(df_DGE = DGE_result,
gene_column = "gene",
pval_column = "p_val_adj_SC_wilcox",
log2fc_column = "avg_log2FC_SC_wilcox",
pval_cutoff = 0.05,
log2fc_cutoff = 0.25,
path = NULL,
filename = "",
species = "Human",
go_catgs = "GO_Biological_Process_2023")
#> Connection changed to https://maayanlab.cloud/Enrichr/
#> Connection is Live!
#> Uploading data to Enrichr... Done.
#> Querying GO_Biological_Process_2023... Done.
#> Parsing results... Done.
#> Uploading data to Enrichr... Done.
#> Querying GO_Biological_Process_2023... Done.
#> Parsing results... Done.
head(result_GO,5) %>%
kable(format = "html", table.attr = "style='width:100%;'") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed", "responsive"))
Term | Overlap | P.value | Adjusted.P.value | Old.P.value | Old.Adjusted.P.value | Odds.Ratio | Combined.Score | Genes | Database | State |
---|---|---|---|---|---|---|---|---|---|---|
Positive Regulation Of Cytokine Production (GO:0001819) | 23/320 | 0 | 0e+00 | 0 | 0 | 9.103525 | 279.79161 | EGR1;CD74;CEBPB;ANXA1;F2R;TWIST1;RORA;ISG15;TNF;SLC7A5;RGCC;PTPRC;IFNG;IRF4;NLRP3;CCR7;IL6ST;TIGIT;GAPDH;CD200;HSPA1B;HLA-DPA1;HSPA1A | GO_Biological_Process_2023 | enriched |
Negative Regulation Of Transcription By RNA Polymerase II (GO:0000122) | 29/763 | 0 | 2e-07 | 0 | 0 | 4.710771 | 106.17869 | CEBPA;CEBPB;CITED2;HMGB2;TWIST1;PRDM1;TNF;ZFP36;TRPS1;KLF10;JUN;CAV1;IRF2BP2;KLF4;SAP30;NR4A2;ETV7;ZEB2;MAF;NR4A3;BCL6;IFNG;ID2;ID1;BHLHE40;ID3;FOSB;ATF3;HSPA1A | GO_Biological_Process_2023 | enriched |
Regulation Of Transcription By RNA Polymerase II (GO:0006357) | 49/2028 | 0 | 3e-07 | 0 | 0 | 3.153714 | 67.92806 | CITED2;HMGB2;RORA;PRDM1;IKZF2;TNF;ZFP36;TRPS1;NAMPT;KDM6B;KLF10;TET2;FOS;ETV3;SAP30;ETV7;TOX2;ZEB2;MAF;IFNG;IRF4;ATF3;CEBPA;CEBPB;TWIST1;RBBP8;NLRP3;HES4;EGR1;JUN;EGR3;CAV1;IRF2BP2;KLF4;FOSL2;NR4A2;NFKBIA;NR4A1;KLF6;RGCC;NR4A3;BCL6;ID2;ID1;BHLHE40;REL;ID3;FOSB;HSPA1A | GO_Biological_Process_2023 | enriched |
Regulation Of DNA-templated Transcription (GO:0006355) | 47/1922 | 0 | 4e-07 | 0 | 0 | 3.166167 | 66.49666 | CDKN1C;CEBPA;CEBPB;CITED2;HMGB2;TWIST1;RORA;PRDM1;IKZF2;TNF;ZFP36L2;BASP1;TRPS1;RBBP8;TNFRSF4;HES4;KLF10;EGR1;CD74;JUN;EGR3;F2R;IRF2BP2;FOS;ETV3;KLF4;SAP30;FOSL2;NR4A2;ETV7;NR4A1;TOX2;ZEB2;KLF6;MAF;NR4A3;BCL6;IFNG;IRF4;ID2;ID1;BHLHE40;REL;ID3;FOSB;ATF3;HLA-DRB1 | GO_Biological_Process_2023 | enriched |
Negative Regulation Of DNA-templated Transcription (GO:0045892) | 32/1025 | 0 | 9e-07 | 0 | 0 | 3.862554 | 76.86009 | CDKN1C;CEBPA;CEBPB;CITED2;HMGB2;TWIST1;PRDM1;TNF;ZFP36;BASP1;TRPS1;TNFRSF4;KLF10;JUN;CAV1;IRF2BP2;KLF4;SAP30;NR4A2;ETV7;ZEB2;MAF;NR4A3;BCL6;IFNG;ID2;ID1;BHLHE40;ID3;FOSB;ATF3;HSPA1A | GO_Biological_Process_2023 | enriched |
The top significant results can then be visualized in a bar plot.
result_GO_sig <- result_GO[result_GO$Adjusted.P.value < 0.05, ]
result_GO_sig$celltype <- "CD4T_cells"
DO.SplitBarGSEA(df_GSEA = result_GO_sig,
term_col = "Term",
col_split = "Combined.Score",
cond_col = "State",
pos_cond = "enriched",
showP = FALSE,
path = paste0(base, "/"))
GSEA_plot <- list.files(path = base, pattern = "SplitBar.*\\.svg$", full.names = TRUE, recursive = TRUE)
plot(magick::image_read_svg(GSEA_plot))
Session information
#> ─ Session info ───────────────────────────────────────────────────────────────────────────────────────────────────────
#> setting value
#> version R version 4.5.1 (2025-06-13)
#> os Ubuntu 24.04.2 LTS
#> system x86_64, linux-gnu
#> ui X11
#> language en
#> collate en_US.UTF-8
#> ctype en_US.UTF-8
#> tz Europe/Berlin
#> date 2025-07-26
#> pandoc 3.4 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/tools/x86_64/ (via rmarkdown)
#> quarto 1.6.42 @ /usr/lib/rstudio/resources/app/bin/quarto/bin/quarto
#>
#> ─ Packages ───────────────────────────────────────────────────────────────────────────────────────────────────────────
#> package * version date (UTC) lib source
#> abind 1.4-8 2024-09-12 [2] CRAN (R 4.5.0)
#> backports 1.5.0 2024-05-23 [2] CRAN (R 4.5.0)
#> basilisk 1.20.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.1)
#> basilisk.utils 1.20.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> beachmat 2.24.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> Biobase 2.68.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> BiocGenerics 0.54.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> BiocManager 1.30.26 2025-06-05 [2] CRAN (R 4.5.0)
#> BiocParallel 1.42.1 2025-06-01 [2] Bioconductor 3.21 (R 4.5.0)
#> BiocStyle * 2.36.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> bookdown 0.43 2025-04-15 [2] CRAN (R 4.5.0)
#> broom 1.0.8 2025-03-28 [2] CRAN (R 4.5.0)
#> bslib 0.9.0 2025-01-30 [2] CRAN (R 4.5.0)
#> cachem 1.1.0 2024-05-16 [2] CRAN (R 4.5.0)
#> car 3.1-3 2024-09-27 [2] CRAN (R 4.5.0)
#> carData 3.0-5 2022-01-06 [2] CRAN (R 4.5.0)
#> cli 3.6.5 2025-04-23 [2] CRAN (R 4.5.0)
#> cluster 2.1.8.1 2025-03-12 [5] CRAN (R 4.4.3)
#> codetools 0.2-20 2024-03-31 [5] CRAN (R 4.4.0)
#> cowplot 1.1.3 2024-01-22 [2] CRAN (R 4.5.0)
#> crayon 1.5.3 2024-06-20 [2] CRAN (R 4.5.0)
#> curl 6.3.0 2025-06-06 [2] CRAN (R 4.5.0)
#> data.table 1.17.4 2025-05-26 [2] CRAN (R 4.5.0)
#> DelayedArray 0.34.1 2025-04-17 [2] Bioconductor 3.21 (R 4.5.0)
#> DelayedMatrixStats 1.30.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> deldir 2.0-4 2024-02-28 [2] CRAN (R 4.5.0)
#> desc 1.4.3 2023-12-10 [2] CRAN (R 4.5.0)
#> DESeq2 1.48.1 2025-05-11 [2] Bioconductor 3.21 (R 4.5.0)
#> digest 0.6.37 2024-08-19 [2] CRAN (R 4.5.0)
#> dir.expiry 1.16.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> dotCall64 1.2 2024-10-04 [2] CRAN (R 4.5.0)
#> DOtools * 0.99.0 2025-07-26 [1] Bioconductor
#> dplyr * 1.1.4 2023-11-17 [2] CRAN (R 4.5.0)
#> dqrng 0.4.1 2024-05-28 [2] CRAN (R 4.5.0)
#> DropletUtils 1.28.0 2025-04-17 [2] Bioconductor 3.21 (R 4.5.0)
#> edgeR 4.6.2 2025-05-07 [2] Bioconductor 3.21 (R 4.5.0)
#> enrichR * 3.4 2025-02-02 [2] CRAN (R 4.5.0)
#> evaluate 1.0.3 2025-01-10 [2] CRAN (R 4.5.0)
#> farver 2.1.2 2024-05-13 [2] CRAN (R 4.5.0)
#> fastDummies 1.7.5 2025-01-20 [2] CRAN (R 4.5.0)
#> fastmap 1.2.0 2024-05-15 [2] CRAN (R 4.5.0)
#> filelock 1.0.3 2023-12-11 [2] CRAN (R 4.5.0)
#> fitdistrplus 1.2-2 2025-01-07 [2] CRAN (R 4.5.0)
#> Formula 1.2-5 2023-02-24 [2] CRAN (R 4.5.0)
#> fs 1.6.6 2025-04-12 [2] CRAN (R 4.5.0)
#> future * 1.58.0 2025-06-05 [2] CRAN (R 4.5.0)
#> future.apply 1.20.0 2025-06-06 [2] CRAN (R 4.5.0)
#> generics 0.1.4 2025-05-09 [2] CRAN (R 4.5.0)
#> GenomeInfoDb 1.44.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> GenomeInfoDbData 1.2.14 2025-05-13 [2] Bioconductor
#> GenomicRanges 1.60.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> ggalluvial 0.12.5 2023-02-22 [2] CRAN (R 4.5.0)
#> ggcorrplot 0.1.4.1 2023-09-05 [2] CRAN (R 4.5.1)
#> ggiraph 0.8.13 2025-03-28 [2] CRAN (R 4.5.0)
#> ggiraphExtra 0.3.0 2020-10-06 [2] CRAN (R 4.5.0)
#> ggplot2 3.5.2 2025-04-09 [2] CRAN (R 4.5.0)
#> ggpubr 0.6.0 2023-02-10 [2] CRAN (R 4.5.0)
#> ggrepel 0.9.6 2024-09-07 [2] CRAN (R 4.5.0)
#> ggridges 0.5.6 2024-01-23 [2] CRAN (R 4.5.0)
#> ggsignif 0.6.4 2022-10-13 [2] CRAN (R 4.5.0)
#> ggtext 0.1.2 2022-09-16 [2] CRAN (R 4.5.0)
#> globals 0.18.0 2025-05-08 [2] CRAN (R 4.5.0)
#> glue 1.8.0 2024-09-30 [2] CRAN (R 4.5.0)
#> goftest 1.2-3 2021-10-07 [2] CRAN (R 4.5.0)
#> gridExtra 2.3 2017-09-09 [2] CRAN (R 4.5.0)
#> gridtext 0.1.5 2022-09-16 [2] CRAN (R 4.5.0)
#> gtable 0.3.6 2024-10-25 [2] CRAN (R 4.5.0)
#> h5mread 1.0.1 2025-05-21 [2] Bioconductor 3.21 (R 4.5.0)
#> HDF5Array 1.36.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> hms 1.1.3 2023-03-21 [2] CRAN (R 4.5.0)
#> htmltools 0.5.8.1 2024-04-04 [2] CRAN (R 4.5.0)
#> htmlwidgets 1.6.4 2023-12-06 [2] CRAN (R 4.5.0)
#> httpuv 1.6.16 2025-04-16 [2] CRAN (R 4.5.0)
#> httr 1.4.7 2023-08-15 [2] CRAN (R 4.5.0)
#> ica 1.0-3 2022-07-08 [2] CRAN (R 4.5.0)
#> igraph 2.1.4 2025-01-23 [2] CRAN (R 4.5.0)
#> insight 1.3.0 2025-05-20 [2] CRAN (R 4.5.0)
#> IRanges 2.42.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> irlba 2.3.5.1 2022-10-03 [2] CRAN (R 4.5.0)
#> jquerylib 0.1.4 2021-04-26 [2] CRAN (R 4.5.0)
#> jsonlite 2.0.0 2025-03-27 [2] CRAN (R 4.5.0)
#> kableExtra * 1.4.0 2024-01-24 [2] CRAN (R 4.5.1)
#> KernSmooth 2.23-26 2025-01-01 [5] CRAN (R 4.4.2)
#> knitr 1.50 2025-03-16 [2] CRAN (R 4.5.0)
#> labeling 0.4.3 2023-08-29 [2] CRAN (R 4.5.0)
#> later 1.4.2 2025-04-08 [2] CRAN (R 4.5.0)
#> lattice 0.22-5 2023-10-24 [5] CRAN (R 4.3.3)
#> lazyeval 0.2.2 2019-03-15 [2] CRAN (R 4.5.0)
#> leidenbase 0.1.35 2025-04-02 [2] CRAN (R 4.5.0)
#> lifecycle 1.0.4 2023-11-07 [2] CRAN (R 4.5.0)
#> limma 3.64.1 2025-05-25 [2] Bioconductor 3.21 (R 4.5.0)
#> listenv 0.9.1 2024-01-29 [2] CRAN (R 4.5.0)
#> lmtest 0.9-40 2022-03-21 [2] CRAN (R 4.5.0)
#> locfit 1.5-9.12 2025-03-05 [2] CRAN (R 4.5.0)
#> magick 2.8.7 2025-06-06 [2] CRAN (R 4.5.0)
#> magrittr 2.0.3 2022-03-30 [2] CRAN (R 4.5.0)
#> MASS 7.3-65 2025-02-28 [5] CRAN (R 4.4.3)
#> Matrix 1.7-3 2025-03-11 [5] CRAN (R 4.4.3)
#> MatrixGenerics 1.20.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> matrixStats 1.5.0 2025-01-07 [2] CRAN (R 4.5.0)
#> mgcv 1.9-1 2023-12-21 [5] CRAN (R 4.3.2)
#> mime 0.13 2025-03-17 [2] CRAN (R 4.5.0)
#> miniUI 0.1.2 2025-04-17 [2] CRAN (R 4.5.0)
#> mycor 0.1.1 2018-04-10 [2] CRAN (R 4.5.0)
#> nlme 3.1-168 2025-03-31 [5] CRAN (R 4.4.3)
#> openxlsx 4.2.8 2025-01-25 [2] CRAN (R 4.5.0)
#> parallelly 1.45.0 2025-06-02 [2] CRAN (R 4.5.0)
#> patchwork 1.3.0 2024-09-16 [2] CRAN (R 4.5.0)
#> pbapply 1.7-2 2023-06-27 [2] CRAN (R 4.5.0)
#> pillar 1.10.2 2025-04-05 [2] CRAN (R 4.5.0)
#> pkgconfig 2.0.3 2019-09-22 [2] CRAN (R 4.5.0)
#> pkgdown 2.1.3 2025-05-25 [2] CRAN (R 4.5.0)
#> plotly 4.10.4 2024-01-13 [2] CRAN (R 4.5.0)
#> plyr * 1.8.9 2023-10-02 [2] CRAN (R 4.5.0)
#> png 0.1-8 2022-11-29 [2] CRAN (R 4.5.0)
#> polyclip 1.10-7 2024-07-23 [2] CRAN (R 4.5.0)
#> ppcor 1.1 2015-12-03 [2] CRAN (R 4.5.0)
#> presto 1.0.0 2025-05-22 [2] Github (immunogenomics/presto@7636b3d)
#> prettyunits 1.2.0 2023-09-24 [2] CRAN (R 4.5.0)
#> progress 1.2.3 2023-12-06 [2] CRAN (R 4.5.0)
#> progressr 0.15.1 2024-11-22 [2] CRAN (R 4.5.0)
#> promises 1.3.3 2025-05-29 [2] CRAN (R 4.5.0)
#> purrr 1.0.4 2025-02-05 [2] CRAN (R 4.5.0)
#> R.methodsS3 1.8.2 2022-06-13 [2] CRAN (R 4.5.0)
#> R.oo 1.27.1 2025-05-02 [2] CRAN (R 4.5.0)
#> R.utils 2.13.0 2025-02-24 [2] CRAN (R 4.5.0)
#> R6 2.6.1 2025-02-15 [2] CRAN (R 4.5.0)
#> ragg 1.4.0 2025-04-10 [2] CRAN (R 4.5.0)
#> RANN 2.6.2 2024-08-25 [2] CRAN (R 4.5.0)
#> RColorBrewer 1.1-3 2022-04-03 [2] CRAN (R 4.5.0)
#> Rcpp 1.0.14 2025-01-12 [2] CRAN (R 4.5.0)
#> RcppAnnoy 0.0.22 2024-01-23 [2] CRAN (R 4.5.0)
#> RcppHNSW 0.6.0 2024-02-04 [2] CRAN (R 4.5.0)
#> reshape2 1.4.4 2020-04-09 [2] CRAN (R 4.5.0)
#> reticulate 1.42.0 2025-03-25 [2] CRAN (R 4.5.0)
#> rhdf5 2.52.1 2025-06-08 [2] Bioconductor 3.21 (R 4.5.0)
#> rhdf5filters 1.20.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> Rhdf5lib 1.30.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> rjson 0.2.23 2024-09-16 [2] CRAN (R 4.5.0)
#> rlang 1.1.6 2025-04-11 [2] CRAN (R 4.5.0)
#> rmarkdown 2.29 2024-11-04 [2] CRAN (R 4.5.0)
#> ROCR 1.0-11 2020-05-02 [2] CRAN (R 4.5.0)
#> RSpectra 0.16-2 2024-07-18 [2] CRAN (R 4.5.0)
#> rstatix 0.7.2 2023-02-01 [2] CRAN (R 4.5.0)
#> rstudioapi 0.17.1 2024-10-22 [2] CRAN (R 4.5.0)
#> rsvg 2.6.2 2025-03-23 [2] CRAN (R 4.5.1)
#> Rtsne 0.17 2023-12-07 [2] CRAN (R 4.5.0)
#> S4Arrays 1.8.1 2025-06-01 [2] Bioconductor 3.21 (R 4.5.0)
#> S4Vectors 0.46.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> sass 0.4.10 2025-04-11 [2] CRAN (R 4.5.0)
#> scales 1.4.0 2025-04-24 [2] CRAN (R 4.5.0)
#> scattermore 1.2 2023-06-12 [2] CRAN (R 4.5.0)
#> sctransform 0.4.2 2025-04-30 [2] CRAN (R 4.5.0)
#> scuttle 1.18.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> sessioninfo 1.2.3 2025-02-05 [2] CRAN (R 4.5.0)
#> Seurat * 5.3.0 2025-04-23 [2] CRAN (R 4.5.0)
#> SeuratObject * 5.1.0 2025-04-22 [2] CRAN (R 4.5.0)
#> shiny 1.10.0 2024-12-14 [2] CRAN (R 4.5.0)
#> SingleCellExperiment 1.30.1 2025-05-07 [2] Bioconductor 3.21 (R 4.5.0)
#> sjlabelled 1.2.0 2022-04-10 [2] CRAN (R 4.5.0)
#> sjmisc 2.8.10 2024-05-13 [2] CRAN (R 4.5.0)
#> sp * 2.2-0 2025-02-01 [2] CRAN (R 4.5.0)
#> spam 2.11-1 2025-01-20 [2] CRAN (R 4.5.0)
#> SparseArray 1.8.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> sparseMatrixStats 1.20.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> spatstat.data 3.1-6 2025-03-17 [2] CRAN (R 4.5.0)
#> spatstat.explore 3.4-3 2025-05-21 [2] CRAN (R 4.5.0)
#> spatstat.geom 3.4-1 2025-05-20 [2] CRAN (R 4.5.0)
#> spatstat.random 3.4-1 2025-05-20 [2] CRAN (R 4.5.0)
#> spatstat.sparse 3.1-0 2024-06-21 [2] CRAN (R 4.5.0)
#> spatstat.univar 3.1-3 2025-05-08 [2] CRAN (R 4.5.0)
#> spatstat.utils 3.1-4 2025-05-15 [2] CRAN (R 4.5.0)
#> statmod 1.5.0 2023-01-06 [2] CRAN (R 4.5.0)
#> stringi 1.8.7 2025-03-27 [2] CRAN (R 4.5.0)
#> stringr 1.5.1 2023-11-14 [2] CRAN (R 4.5.0)
#> SummarizedExperiment 1.38.1 2025-04-30 [2] Bioconductor 3.21 (R 4.5.0)
#> survival 3.8-3 2024-12-17 [5] CRAN (R 4.4.2)
#> svglite 2.2.1 2025-05-12 [2] CRAN (R 4.5.0)
#> systemfonts 1.2.3 2025-04-30 [2] CRAN (R 4.5.0)
#> tensor 1.5 2012-05-05 [2] CRAN (R 4.5.0)
#> textshaping 1.0.1 2025-05-01 [2] CRAN (R 4.5.0)
#> tibble * 3.3.0 2025-06-08 [2] CRAN (R 4.5.0)
#> tidyr 1.3.1 2024-01-24 [2] CRAN (R 4.5.0)
#> tidyselect 1.2.1 2024-03-11 [2] CRAN (R 4.5.0)
#> tidyverse 2.0.0 2023-02-22 [2] CRAN (R 4.5.0)
#> UCSC.utils 1.4.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> uuid 1.2-1 2024-07-29 [2] CRAN (R 4.5.0)
#> uwot 0.2.3 2025-02-24 [2] CRAN (R 4.5.0)
#> vctrs 0.6.5 2023-12-01 [2] CRAN (R 4.5.0)
#> viridisLite 0.4.2 2023-05-02 [2] CRAN (R 4.5.0)
#> withr 3.0.2 2024-10-28 [2] CRAN (R 4.5.0)
#> WriteXLS 6.8.0 2025-05-22 [2] CRAN (R 4.5.0)
#> xfun 0.52 2025-04-02 [2] CRAN (R 4.5.0)
#> xml2 1.3.8 2025-03-14 [2] CRAN (R 4.5.0)
#> xtable 1.8-4 2019-04-21 [2] CRAN (R 4.5.0)
#> XVector 0.48.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> yaml 2.3.10 2024-07-26 [2] CRAN (R 4.5.0)
#> zellkonverter 1.18.0 2025-04-15 [2] Bioconductor 3.21 (R 4.5.0)
#> zip 2.3.3 2025-05-13 [2] CRAN (R 4.5.0)
#> zoo 1.8-14 2025-04-10 [2] CRAN (R 4.5.0)
#>
#> [1] /tmp/RtmprTfcJ4/temp_libpath154da34875cff
#> [2] /home/mariano/R/x86_64-pc-linux-gnu-library/4.5
#> [3] /usr/local/lib/R/site-library
#> [4] /usr/lib/R/site-library
#> [5] /usr/lib/R/library
#> * ── Packages attached to the search path.
#>
#> ─ Python configuration ───────────────────────────────────────────────────────────────────────────────────────────────
#> python: /home/mariano/.cache/R/basilisk/1.20.0/zellkonverter/1.18.0/zellkonverterAnnDataEnv-0.11.4/bin/python
#> libpython: /home/mariano/.cache/R/basilisk/1.20.0/zellkonverter/1.18.0/zellkonverterAnnDataEnv-0.11.4/lib/libpython3.13.so
#> pythonhome: /home/mariano/.cache/R/basilisk/1.20.0/zellkonverter/1.18.0/zellkonverterAnnDataEnv-0.11.4:/home/mariano/.cache/R/basilisk/1.20.0/zellkonverter/1.18.0/zellkonverterAnnDataEnv-0.11.4
#> version: 3.13.2 | packaged by conda-forge | (main, Feb 17 2025, 14:10:22) [GCC 13.3.0]
#> numpy: /home/mariano/.cache/R/basilisk/1.20.0/zellkonverter/1.18.0/zellkonverterAnnDataEnv-0.11.4/lib/python3.13/site-packages/numpy
#> numpy_version: 2.2.4
#>
#> NOTE: Python version was forced by use_python() function
#>
#> ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────