From d708f7c338631f3d5695a3b4fcd490c19e3fc967 Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Thu, 13 Nov 2025 15:16:52 -0500 Subject: [PATCH 01/23] feat: tests and plotting function updates --- DESCRIPTION | 10 +++ R/fetch_celldex_ref.R | 60 +++++++++++++ R/make_bubble_plot.R | 59 +++++-------- R/make_volcano_plot.R | 69 +++++++++++++++ R/run_singleR.R | 6 ++ R/run_singleR_cluster.R | 15 +++- R/run_singleR_db.R | 83 ++++++++++++++++- tests/testthat/helper.R | 20 +++++ tests/testthat/test-fetch_celldex_ref.R | 103 ++++++++++++++++++++++ tests/testthat/test-run_singleR.R | 17 ++++ tests/testthat/test-run_singleR_cluster.R | 25 ++++++ 11 files changed, 428 insertions(+), 39 deletions(-) create mode 100644 R/fetch_celldex_ref.R create mode 100644 tests/testthat/helper.R create mode 100644 tests/testthat/test-fetch_celldex_ref.R create mode 100644 tests/testthat/test-run_singleR.R create mode 100644 tests/testthat/test-run_singleR_cluster.R diff --git a/DESCRIPTION b/DESCRIPTION index 88e9560..e8121fc 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -22,6 +22,7 @@ Imports: DropletUtils, ggplot2, ggpubr, + ggrepel, grDevices, harmony, magrittr, @@ -34,8 +35,13 @@ Imports: rliger, scDblFinder, Seurat, +<<<<<<< HEAD SeuratObject, SeuratWrappers, +======= + SeuratData, + SingleCellExperiment, +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) SingleR, stats, utils @@ -49,12 +55,16 @@ Suggests: SingleCellExperiment, testthat (>= 3.0.0), usethis +<<<<<<< HEAD Remotes: chris-mcginnis-ucsf/DoubletFinder, rnabioco/djvdj@*release, SeuratWrappers=satijalab/seurat-wrappers biocViews: Config/Needs/check: rcmdcheck, lintr, goodpractice +======= +biocViews: +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) Config/testthat/edition: 3 Encoding: UTF-8 Roxygen: list(markdown = TRUE) diff --git a/R/fetch_celldex_ref.R b/R/fetch_celldex_ref.R new file mode 100644 index 0000000..7ec3aa1 --- /dev/null +++ b/R/fetch_celldex_ref.R @@ -0,0 +1,60 @@ +#' fetch_celldex_ref: Helper function to import annotation references from +#' celldex +#' +#' @description Retrieves one of the 7 available references in celldex. Should +#' be cache-agnostic by declaring the cache location as the local working +#' directory +#' +#' @import celldex +#' @import SingleR +#' +#' @export +#' +#' @return A celldex single cell object in SCE data structure +fetch_celldex_ref <- function(ref_name) { + ref <- switch(ref_name, + "hpca" = , + "HumanPrimaryCellAtlasData" = celldex::fetchReference( + "hpca", + version = "2024-02-26", + realize.assays = TRUE, cache = "./" + ), + "blueprint_encode" = , + "BP_encode" = , + "bpencode" = , + "bp_encode" = , + "BlueprintEncodeData" = celldex::fetchReference( + "blueprint_encode", "2024-02-26", + realize.assays = TRUE, cache = "./" + ), + "monaco" = , + "MonacoImmuneData" = celldex::fetchReference( + "monaco_immune", "2024-02-26", + realize.assays = TRUE, cache = "./" + ), + "immu_cell_exp" = , + "DatabaseImmuneCellExpressionData" = , + "dice" = celldex::fetchReference( + "dice", "2024-02-26", + realize.assays = TRUE, cache = "./" + ), + "hematopoietic" = , + "NovershternHematopoieticData" = , + "novershtern_hematopoietic" = , + "novershtern" = celldex::fetchReference( + "novershtern_hematopoietic", "2024-02-26", + realize.assays = TRUE, cache = "./" + ), + "immgen" = , + "ImmGenData" = celldex::fetchReference( + "immgen", "2024-02-26", + realize.assays = TRUE, cache = "./" + ), + "mouseRNAseq" = , + "MouseRNAseqData" = celldex::fetchReference( + "mouse_rnaseq", "2024-02-26", + realize.assays = TRUE, cache = "./" + ) + ) + return(ref) +} diff --git a/R/make_bubble_plot.R b/R/make_bubble_plot.R index 1f34fbf..1ec5350 100644 --- a/R/make_bubble_plot.R +++ b/R/make_bubble_plot.R @@ -1,4 +1,4 @@ -#' make a flexible bubble plot with Seurat::DotPlot +#' make_bubble_plot: Flexible dotplot #' #' @description Creates a bubble plot that shows average expression percent #' expression for genes in single cell categories @@ -9,55 +9,44 @@ #' @param assay The counts assay to use for determining expression #' @param ident The categorical identity to classify groups of cells #' +#' @import Seurat +#' @import ggplot2 +#' @import dplyr +#' @import reshape2 +#' @import RColorBrewer +#' #' @export #' #' @return A ggplot2 figure #' -make_bubble_plot <- function(so, - features, - palette = "RdBu", - assay = "SCT", - ident = "seurat_clusters") { - # data variables must be initialized to silence the R CMD check note: - # 'no visible binding for global variable' - pct.exp <- id <- features.plot <- group <- Gene <- Pct.Exp <- AvgExp <- NULL - - Seurat::Idents(so) <- ident +make_bubble_plot <- function( + so, features, palette = "RdBu", assay = "SCT", ident = "seurat_clusters" +) { + Idents(so) <- ident - dotplot <- Seurat::DotPlot(so, features = features) + dotplot <- DotPlot(so, features = features) pct_expression <- dplyr::select(dotplot$data, pct.exp, id, features.plot) - avg_expression <- Seurat::AverageExpression(so, assays = assay)[[assay]] + avg_expression <- AverageExpression(so, assay = assay, features = features)[[assay]] avg_expression <- as.matrix(avg_expression) avg_expression_df <- reshape2::melt(avg_expression) - colnames(avg_expression_df) <- c("group", "Gene", "AvgExp") + colnames(avg_expression_df) <- c("Gene", "Group", "AvgExp") avg_expression_df$PctExp <- 0 - - # TODO refactor this with map - for (i in seq_len(avg_expression_df)) { + avg_expression_df$Group <- as.integer(gsub("[^0-9]", "", avg_expression_df$Group)) + for (i in seq_len(nrow(avg_expression_df))) { avg_expression_df[i, 4] <- pct_expression$pct.exp[which( - pct_expression$id == avg_expression_df[ident, i] & + pct_expression$id == avg_expression_df[i, "Group"] & pct_expression$features.plot == avg_expression_df$Gene[i] )] } - bubble_plot <- ggplot2::ggplot( - avg_expression_df, - ggplot2::aes( - x = group, - y = Gene, - size = Pct.Exp, - color = AvgExp - ) - ) + - ggplot2::geom_point() + - ggplot2::scale_color_distiller(palette = palette) + - ggplot2::theme_bw() + - ggplot2::theme(axis.text.x = ggplot2::element_text( - angle = 45, - vjust = 1, - hjust = 1 - )) + plot <- ggplot(avg_expression_df, aes( + x = Group, y = Gene, size = PctExp, color = AvgExp + )) + + geom_point() + + scale_color_distiller(palette = palette) + + theme_bw() + + theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) return(bubble_plot) } diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index 2ef6e5e..60b5bc4 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -9,6 +9,14 @@ #' @param logfc Boolean to color genes meeting logfc threshold of 1.5 #' @param pval Boolean to color genes meeting p-value threshold of 0.05 #' @param significant Boolean to color genes that meet both above thresholds +<<<<<<< HEAD +======= +#' @param label Numeric value of top n genes to label, or a character vector of +#' genes to label. Set label to NULL to generate unlabeled plot +#' +#' @import ggplot2 +#' @import ggrepel +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' #' @export #' @@ -34,10 +42,37 @@ make_volcano_plot <- function(de_table, de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" } +<<<<<<< HEAD +======= +make_volcano_plot <- function( + de_table, + significant = TRUE, + logfc = TRUE, + pval = TRUE, + label = 50 +) { + log10_p <- -log10(de_table$p_val_adj) + log10_p[which(de_table$p_val_adj == 0)] <- 500 + avg_log2FC <- de_table$avg_log2FC + gene <- rownames(de_table) + significance <- vector(length = length(log10_p)) + significance[] <- "NotSignificant" + if (logfc == TRUE) { + significance[which(abs(de_table$avg_log2FC) > 1.5)] <- "avg_log2FC > 1.5" + } + if (pval == TRUE) { + significance[which(de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05" + } + if (significant == T) { + significance[which(abs(de_table$avg_log2FC) > 1.5 & de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" + } + +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) df <- as.data.frame(cbind(avg_log2FC, log10_p, significance, gene)) rownames(df) <- rownames(de_table) df[, 1] <- as.numeric(df[, 1]) df[, 2] <- as.numeric(df[, 2]) +<<<<<<< HEAD df[, 3] <- factor( df[, 3], levels = c( @@ -51,4 +86,38 @@ make_volcano_plot <- function(de_table, volcano <- ggplot2::ggplot(df, ggplot2::aes(x = avg_log2FC, y = log10_p, col = significance)) + ggplot2::geom_point() return(volcano) +======= + df[, 3] <- factor(df[, 3], + levels = c( + "NotSignificant", "avg_log2FC > 1.5", + "p_val_adj < 0.05", "p_val_adj < 0.05 & avg_log2FC > 1.5" + ) + ) + data_subset <- NULL + + if (is.numeric(label) && length(label) == 1) { + data_subset <- df[which(df$significance == "p_val_adj < 0.05 & avg_log2FC > 1.5"), ] + data_subset <- data_subset[1:label, ] + } else if (is.character(label)) { + data_subset <- df[label, ] + } + + + volcano <- ggplot(df, aes(x = avg_log2FC, y = log10_p, col = significance)) + + geom_point() + + # geom_vline(xintercept = 0, color = "black", linewidth = 1.5)+ + xlim(-ceiling(max(abs(df$avg_log2FC))), ceiling(max(abs(df$avg_log2FC)))) + + if (!is.null(data_subset)) { + volcano <- volcano + + geom_text_repel( + aes(label = gene), + data_subset, + color = "black", + max.overlaps = Inf + ) + + return(volcano) + } +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) } diff --git a/R/run_singleR.R b/R/run_singleR.R index cd841fe..211e405 100644 --- a/R/run_singleR.R +++ b/R/run_singleR.R @@ -7,6 +7,12 @@ #' package #' @param label The label identity to be used. Must be a column header in the metadata of `ref_file` #' +<<<<<<< HEAD +======= +#' @import SingleR +#' @import Seurat +#' +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' @export #' #' @return A vector of pruned cell type labels diff --git a/R/run_singleR_cluster.R b/R/run_singleR_cluster.R index 0ab8ff7..2282e58 100644 --- a/R/run_singleR_cluster.R +++ b/R/run_singleR_cluster.R @@ -8,12 +8,19 @@ #' (SingleCellExperiment object) #' @param label A cell type label from the metadata column headers #' +<<<<<<< HEAD +======= +#' @import celldex +#' @import SingleR +#' +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' @export #' #' @return A character vector of matched cell type annotations based on #' clusters #' run_singleR_cluster <- function(so_in, ref_file, label) { +<<<<<<< HEAD avg <- Seurat::AverageExpression(so_in, assays = "SCT") avg <- as.data.frame(avg) ref <- ref_file @@ -22,10 +29,16 @@ run_singleR_cluster <- function(so_in, ref_file, label) { ref = ref, labels = ref[[label]] ) +======= + avg <- AverageExpression(so_in, assays = "SCT")$SCT + avg <- as.data.frame(avg) + ref <- ref_file + s <- SingleR(test = as.matrix(avg), ref = ref, labels = ref[[label]]) +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) clust_annot <- s$labels names(clust_annot) <- colnames(avg) - names(clust_annot) <- gsub("SCT.", "", names(clust_annot)) + names(clust_annot) <- gsub("[^0-9]", "", names(clust_annot)) annot_vect <- clust_annot[match(so_in$seurat_clusters, names(clust_annot))] names(annot_vect) <- colnames(so_in) diff --git a/R/run_singleR_db.R b/R/run_singleR_db.R index 06274e0..727e0a4 100644 --- a/R/run_singleR_db.R +++ b/R/run_singleR_db.R @@ -7,13 +7,30 @@ #' @param species Indicates human (hg19 or hg38) or mouse (mm10) references to #' be used #' +<<<<<<< HEAD +======= +#' @import SingleR +#' @import celldex +#' @import ontoProc +#' +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' @export #' #' @return A Seurat single cell object with predicted cell type annotations run_singleR_db <- function(so_in, species) { + # NOTE BEFORE NEXT PUSH: BUILD FUNCTION TO RETRIEVE SINGLE CELL REFERENCE OBJECTS EXTERNALLY + + # fetch_singleR_references <- function(ref = NULL){ + + # <- celldex::HumanPrimaryCellAtlasData() + # } + + # fetch_singleR_references() #Populates references into R environment + cell_ont <- ontoProc::getOnto("cellOnto") if (species == "hg38" || species == "hg19") { so_in$HPCA_main <- run_singleR( +<<<<<<< HEAD so_in, celldex::HumanPrimaryCellAtlasData(), "label.main" @@ -22,10 +39,20 @@ run_singleR_db <- function(so_in, species) { so_in, celldex::HumanPrimaryCellAtlasData(), "label.fine" +======= + so_in, fetch_celldex_ref("hpca"), "label.main" + ) + so_in$HPCA_fine <- run_singleR( + so_in, fetch_celldex_ref("hpca"), "label.fine" + ) + so_in$HPCA_ont <- run_singleR( + so_in, fetch_celldex_ref("hpca"), "label.ont" +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) ) so_in$HPCA_ont <- run_singleR(so_in, celldex::HumanPrimaryCellAtlasData(), "label.ont") so_in$HPCA_ont <- cell_ont$name[so_in$HPCA_ont] +<<<<<<< HEAD so_in$BP_encode_main <- run_singleR(so_in, celldex::BlueprintEncodeData(), "label.main") so_in$BP_encode_fine <- run_singleR(so_in, celldex::BlueprintEncodeData(), "label.fine") so_in$BP_encode_ont <- run_singleR(so_in, celldex::BlueprintEncodeData()(), "label.ont") @@ -50,18 +77,68 @@ run_singleR_db <- function(so_in, species) { so_in, celldex::DatabaseImmuneCellExpressionData(), "label.ont" +======= + so_in$BP_encode_main <- run_singleR( + so_in, fetch_celldex_ref("BP_encode"), "label.main" + ) + so_in$BP_encode_fine <- run_singleR( + so_in, fetch_celldex_ref("BP_encode"), "label.fine" + ) + so_in$BP_encode_ont <- run_singleR( + so_in, fetch_celldex_ref("BP_encode"), "label.ont" + ) + so_in$BP_encode_ont <- cell_ont$name[so_in$BP_encode_ont] + + so_in$monaco_main <- run_singleR( + so_in, fetch_celldex_ref("monaco"), "label.main" + ) + so_in$monaco_fine <- run_singleR( + so_in, fetch_celldex_ref("monaco"), "label.fine" + ) + so_in$monaco_ont <- run_singleR( + so_in, fetch_celldex_ref("monaco"), "label.ont" + ) + so_in$monaco_ont <- cell_ont$name[so_in$monaco_ont] + + so_in$immu_cell_exp_main <- run_singleR( + so_in, fetch_celldex_ref("dice"), "label.main" + ) + so_in$immu_cell_exp_fine <- run_singleR( + so_in, fetch_celldex_ref("dice"), "label.fine" + ) + so_in$immu_cell_exp_ont <- run_singleR( + so_in, fetch_celldex_ref("dice"), "label.ont" +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) ) so_in$immu_cell_exp_ont <- cell_ont$name[so_in$immu_cell_exp_ont] so_in$annot <- so_in$HPCA_main } else if (species == "mm10") { - so_in$immgen_main <- run_singleR(so_in, celldex::ImmGenData(), "label.main") - so_in$immgen_fine <- run_singleR(so_in, celldex::ImmGenData(), "label.fine") - so_in$immgen_ont <- run_singleR(so_in, celldex::ImmGenData(), "label.ont") + so_in$immgen_main <- run_singleR( + so_in, fetch_celldex_ref("immgen"), "label.main" + ) + so_in$immgen_fine <- run_singleR( + so_in, fetch_celldex_ref("immgen"), "label.fine" + ) + so_in$immgen_ont <- run_singleR( + so_in, fetch_celldex_ref("immgen"), "label.ont" + ) so_in$immgen_ont <- cell_ont$name[so_in$immgen_ont] +<<<<<<< HEAD so_in$mouseRNAseq_main <- run_singleR(so_in, celldex::MouseRNAseqData(), "label.main") so_in$mouseRNAseq_fine <- run_singleR(so_in, celldex::MouseRNAseqData(), "label.fine") so_in$mouseRNAseq_ont <- run_singleR(so_in, celldex::MouseRNAseqData(), "label.ont") +======= + so_in$mouseRNAseq_main <- run_singleR( + so_in, fetch_celldex_ref("mouseRNAseq"), "label.main" + ) + so_in$mouseRNAseq_fine <- run_singleR( + so_in, fetch_celldex_ref("mouseRNAseq"), "label.fine" + ) + so_in$mouseRNAseq_ont <- run_singleR( + so_in, fetch_celldex_ref("mouseRNAseq"), "label.ont" + ) +>>>>>>> 6c9f3fa (feat: tests and plotting function updates) so_in$mouseRNAseq_ont <- cell_ont$name[so_in$mouseRNAseq_ont] so_in$annot <- so_in$immgen_main diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R new file mode 100644 index 0000000..cda42d2 --- /dev/null +++ b/tests/testthat/helper.R @@ -0,0 +1,20 @@ +import_pbmc <- function() { + if (grepl("pbmc3k", SeuratData::InstalledData()[1]) == FALSE) { + SeuratData::InstallData("pbmc3k") + } + + # prepare test dataset + pbmc3k <- suppressWarnings(SeuratData::LoadData("pbmc3k")) + pbmc <- UpdateSeuratObject(pbmc3k) + set.seed(42) + pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-") + pbmc <- subset(pbmc, + subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5 + ) + pbmc <- SCTransform(pbmc, vars.to.regress = "percent.mt", verbose = FALSE) + pbmc <- RunPCA(pbmc, features = VariableFeatures(object = pbmc)) + pbmc <- FindNeighbors(pbmc, dims = 1:30) + pbmc <- FindClusters(pbmc, resolution = 0.8, verbose = FALSE) + + return(pbmc) +} diff --git a/tests/testthat/test-fetch_celldex_ref.R b/tests/testthat/test-fetch_celldex_ref.R new file mode 100644 index 0000000..d1d8487 --- /dev/null +++ b/tests/testthat/test-fetch_celldex_ref.R @@ -0,0 +1,103 @@ +test_that("hpca_import", { + hpca <- fetch_celldex_ref("hpca") + hpca_2 <- fetch_celldex_ref("HumanPrimaryCellAtlasData") + expect_equal(typeof(hpca), "S4") + expect_equal(typeof(hpca_2), "S4") + + expect_equal(ncol(hpca), 713) + expect_equal(ncol(hpca_2), 713) + + expect_equal(nrow(hpca), 19363) + expect_equal(nrow(hpca_2), 19363) +}) + +test_that("bp_encode_import", { + bp <- fetch_celldex_ref("blueprint_encode") + bp_2 <- fetch_celldex_ref("BP_encode") + bp_3 <- fetch_celldex_ref("BlueprintEncodeData") + expect_equal(typeof(bp), "S4") + expect_equal(typeof(bp_2), "S4") + expect_equal(typeof(bp_3), "S4") + + expect_equal(ncol(bp), 259) + expect_equal(ncol(bp_2), 259) + expect_equal(ncol(bp_3), 259) + + expect_equal(nrow(bp), 19859) + expect_equal(nrow(bp_2), 19859) + expect_equal(nrow(bp_3), 19859) +}) + +test_that("monaco_import", { + monaco <- fetch_celldex_ref("monaco") + monaco_2 <- fetch_celldex_ref("MonacoImmuneData") + expect_equal(typeof(monaco), "S4") + expect_equal(typeof(monaco_2), "S4") + + expect_equal(ncol(monaco), 114) + expect_equal(ncol(monaco_2), 114) + + expect_equal(nrow(monaco), 46077) + expect_equal(nrow(monaco_2), 46077) +}) + +test_that("dice_import", { + dice <- fetch_celldex_ref("dice") + dice_2 <- fetch_celldex_ref("DatabaseImmuneCellExpressionData") + expect_equal(typeof(dice), "S4") + expect_equal(typeof(dice_2), "S4") + + expect_equal(ncol(dice), 1561) + expect_equal(ncol(dice_2), 1561) + + expect_equal(nrow(dice), 48043) + expect_equal(nrow(dice_2), 48043) +}) +test_that("noversh_import", { + noversh <- fetch_celldex_ref("hematopoietic") + noversh_2 <- fetch_celldex_ref("NovershternHematopoieticData") + noversh_3 <- fetch_celldex_ref("novershtern") + expect_equal(typeof(noversh), "S4") + expect_equal(typeof(noversh_2), "S4") + expect_equal(typeof(noversh_3), "S4") + + expect_equal(ncol(noversh), 211) + expect_equal(ncol(noversh_2), 211) + expect_equal(ncol(noversh_3), 211) + + expect_equal(nrow(noversh), 13276) + expect_equal(nrow(noversh_2), 13276) + expect_equal(nrow(noversh_3), 13276) +}) +test_that("immgen_import", { + immgen <- fetch_celldex_ref("immgen") + immgen_2 <- fetch_celldex_ref("ImmGenData") + expect_equal(typeof(immgen), "S4") + expect_equal(typeof(immgen_2), "S4") + + expect_equal(ncol(immgen), 830) + expect_equal(ncol(immgen_2), 830) + + expect_equal(nrow(immgen), 22134) + expect_equal(nrow(immgen_2), 22134) +}) + +test_that("mouseRNAseq_import", { + mm_rna <- fetch_celldex_ref("mouseRNAseq") + mm_rna_2 <- fetch_celldex_ref("MouseRNAseqData") + expect_equal(typeof(mm_rna), "S4") + expect_equal(typeof(mm_rna_2), "S4") + + expect_equal(ncol(mm_rna), 358) + expect_equal(ncol(mm_rna_2), 358) + + expect_equal(nrow(mm_rna), 21214) + expect_equal(nrow(mm_rna_2), 21214) +}) + +test_that("non_existent_ref", { + ref_test <- fetch_celldex_ref("blech") + expect_null(ref_test) + expect_error(fetch_celldex_ref(1)) + expect_error(fetch_celldex_ref()) +}) diff --git a/tests/testthat/test-run_singleR.R b/tests/testthat/test-run_singleR.R new file mode 100644 index 0000000..69ceee2 --- /dev/null +++ b/tests/testthat/test-run_singleR.R @@ -0,0 +1,17 @@ +test_that("object_size", { + pbmc <- suppressMessages(import_pbmc()) + expect_equal(ncol(pbmc), 2638) +}) + +test_that("cell_type_annotation", { + pbmc <- suppressMessages(import_pbmc()) + + ref <- fetch_celldex_ref("hpca") + + singleR_output <- run_singleR(pbmc, ref, "label.main") + + expect_equal(length(which(singleR_output == "T_cells")), 1394) + expect_equal(length(which(singleR_output == "B_cell")), 335) + expect_equal(length(which(singleR_output == "Monocyte")), 619) + expect_equal(length(which(singleR_output == "NK_cell")), 185) +}) diff --git a/tests/testthat/test-run_singleR_cluster.R b/tests/testthat/test-run_singleR_cluster.R new file mode 100644 index 0000000..4098a1f --- /dev/null +++ b/tests/testthat/test-run_singleR_cluster.R @@ -0,0 +1,25 @@ +test_that("object_size", { + pbmc <- suppressMessages(import_pbmc()) + expect_equal(ncol(pbmc), 2638) +}) + +test_that("cluster_count", { + pbmc <- suppressMessages(import_pbmc()) + expect_equal(length(unique(pbmc$seurat_clusters)), 12) +}) + +test_that("cluster_cell_annot_type_count", { + pbmc <- suppressMessages(import_pbmc()) + ref <- fetch_celldex_ref("hpca") + Idents(pbmc) <- "seurat_clusters" + singleR_cluster <- run_singleR_cluster( + so_in = pbmc, + ref_file = ref, + label = "label.main" + ) + expect_equal(length(unique(singleR_cluster)), 5) + expect_equal(length(which(singleR_cluster == "B_cell")), 346) + expect_equal(length(which(singleR_cluster == "Monocyte")), 672) + expect_equal(length(which(singleR_cluster == "NK_cell")), 156) + expect_equal(length(which(singleR_cluster == "T_cells")), 1452) +}) From 20fdc004244506868efc928c8777d2698064b10b Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Thu, 13 Nov 2025 15:30:31 -0500 Subject: [PATCH 02/23] Update make_volcano_plot.R --- R/make_volcano_plot.R | 42 ------------------------------------------ 1 file changed, 42 deletions(-) diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index 60b5bc4..bd98465 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -8,42 +8,16 @@ #' p_val, pct.1, pct.2 avg_log2FC and p_val_adj #' @param logfc Boolean to color genes meeting logfc threshold of 1.5 #' @param pval Boolean to color genes meeting p-value threshold of 0.05 -#' @param significant Boolean to color genes that meet both above thresholds -<<<<<<< HEAD -======= #' @param label Numeric value of top n genes to label, or a character vector of #' genes to label. Set label to NULL to generate unlabeled plot #' #' @import ggplot2 #' @import ggrepel ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' #' @export #' #' @return Returns a volcano plot as a ggplot2 object -make_volcano_plot <- function(de_table, - significant = TRUE, - logfc = TRUE, - pval = TRUE) { - log10_p <- -log10(de_table$p_val_adj) - log10_p[which(de_table$p_val_adj == 0)] <- 500 - avg_log2FC <- de_table$avg_log2FC - gene <- rownames(de_table) - significance <- vector(length = length(log10_p)) - significance[] <- "NotSignificant" - if (logfc == TRUE) { - significance[which(abs(de_table$avg_log2FC) > 1.5)] <- "avg_log2FC > 1.5" - } - if (pval == TRUE) { - significance[which(de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05" - } - if (significant == TRUE) { - significance[which(abs(de_table$avg_log2FC) > 1.5 & - de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" - } -<<<<<<< HEAD -======= make_volcano_plot <- function( de_table, significant = TRUE, @@ -72,21 +46,6 @@ make_volcano_plot <- function( rownames(df) <- rownames(de_table) df[, 1] <- as.numeric(df[, 1]) df[, 2] <- as.numeric(df[, 2]) -<<<<<<< HEAD - df[, 3] <- factor( - df[, 3], - levels = c( - "NotSignificant", - "avg_log2FC > 1.5", - "p_val_adj < 0.05", - "p_val_adj < 0.05 & avg_log2FC > 1.5" - ) - ) - - volcano <- ggplot2::ggplot(df, ggplot2::aes(x = avg_log2FC, y = log10_p, col = significance)) + - ggplot2::geom_point() - return(volcano) -======= df[, 3] <- factor(df[, 3], levels = c( "NotSignificant", "avg_log2FC > 1.5", @@ -119,5 +78,4 @@ make_volcano_plot <- function( return(volcano) } ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) } From c576bf53c911efa47c7a90d7f409d49059fc8683 Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Thu, 13 Nov 2025 15:30:54 -0500 Subject: [PATCH 03/23] Update make_volcano_plot.R --- R/make_volcano_plot.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index bd98465..e3d4067 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -40,8 +40,6 @@ make_volcano_plot <- function( if (significant == T) { significance[which(abs(de_table$avg_log2FC) > 1.5 & de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" } - ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) df <- as.data.frame(cbind(avg_log2FC, log10_p, significance, gene)) rownames(df) <- rownames(de_table) df[, 1] <- as.numeric(df[, 1]) From 2540e55437517258e80b169a4ffbc2343874a2c8 Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Thu, 13 Nov 2025 15:37:22 -0500 Subject: [PATCH 04/23] chore: resolve DESCRIPTION merge conflict --- DESCRIPTION | 9 --------- 1 file changed, 9 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index e8121fc..67383d8 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -35,13 +35,8 @@ Imports: rliger, scDblFinder, Seurat, -<<<<<<< HEAD - SeuratObject, - SeuratWrappers, -======= SeuratData, SingleCellExperiment, ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) SingleR, stats, utils @@ -55,16 +50,12 @@ Suggests: SingleCellExperiment, testthat (>= 3.0.0), usethis -<<<<<<< HEAD Remotes: chris-mcginnis-ucsf/DoubletFinder, rnabioco/djvdj@*release, SeuratWrappers=satijalab/seurat-wrappers biocViews: Config/Needs/check: rcmdcheck, lintr, goodpractice -======= -biocViews: ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) Config/testthat/edition: 3 Encoding: UTF-8 Roxygen: list(markdown = TRUE) From c3a5d4a36f5aa104cbe661de8926770e14f820b7 Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Thu, 13 Nov 2025 16:07:00 -0500 Subject: [PATCH 05/23] feat: update singleR commands --- R/run_singleR.R | 3 --- R/run_singleR_cluster.R | 14 ------------ R/run_singleR_db.R | 47 ----------------------------------------- 3 files changed, 64 deletions(-) diff --git a/R/run_singleR.R b/R/run_singleR.R index 211e405..6ca8b9a 100644 --- a/R/run_singleR.R +++ b/R/run_singleR.R @@ -7,12 +7,9 @@ #' package #' @param label The label identity to be used. Must be a column header in the metadata of `ref_file` #' -<<<<<<< HEAD -======= #' @import SingleR #' @import Seurat #' ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' @export #' #' @return A vector of pruned cell type labels diff --git a/R/run_singleR_cluster.R b/R/run_singleR_cluster.R index 2282e58..a0dd63a 100644 --- a/R/run_singleR_cluster.R +++ b/R/run_singleR_cluster.R @@ -8,33 +8,19 @@ #' (SingleCellExperiment object) #' @param label A cell type label from the metadata column headers #' -<<<<<<< HEAD -======= #' @import celldex #' @import SingleR #' ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' @export #' #' @return A character vector of matched cell type annotations based on #' clusters #' run_singleR_cluster <- function(so_in, ref_file, label) { -<<<<<<< HEAD - avg <- Seurat::AverageExpression(so_in, assays = "SCT") - avg <- as.data.frame(avg) - ref <- ref_file - s <- SingleR::SingleR( - test = as.matrix(avg), - ref = ref, - labels = ref[[label]] - ) -======= avg <- AverageExpression(so_in, assays = "SCT")$SCT avg <- as.data.frame(avg) ref <- ref_file s <- SingleR(test = as.matrix(avg), ref = ref, labels = ref[[label]]) ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) clust_annot <- s$labels names(clust_annot) <- colnames(avg) diff --git a/R/run_singleR_db.R b/R/run_singleR_db.R index 727e0a4..4568727 100644 --- a/R/run_singleR_db.R +++ b/R/run_singleR_db.R @@ -7,13 +7,10 @@ #' @param species Indicates human (hg19 or hg38) or mouse (mm10) references to #' be used #' -<<<<<<< HEAD -======= #' @import SingleR #' @import celldex #' @import ontoProc #' ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) #' @export #' #' @return A Seurat single cell object with predicted cell type annotations @@ -30,16 +27,6 @@ run_singleR_db <- function(so_in, species) { cell_ont <- ontoProc::getOnto("cellOnto") if (species == "hg38" || species == "hg19") { so_in$HPCA_main <- run_singleR( -<<<<<<< HEAD - so_in, - celldex::HumanPrimaryCellAtlasData(), - "label.main" - ) - so_in$HPCA_fine <- run_singleR( - so_in, - celldex::HumanPrimaryCellAtlasData(), - "label.fine" -======= so_in, fetch_celldex_ref("hpca"), "label.main" ) so_in$HPCA_fine <- run_singleR( @@ -47,37 +34,10 @@ run_singleR_db <- function(so_in, species) { ) so_in$HPCA_ont <- run_singleR( so_in, fetch_celldex_ref("hpca"), "label.ont" ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) ) so_in$HPCA_ont <- run_singleR(so_in, celldex::HumanPrimaryCellAtlasData(), "label.ont") so_in$HPCA_ont <- cell_ont$name[so_in$HPCA_ont] -<<<<<<< HEAD - so_in$BP_encode_main <- run_singleR(so_in, celldex::BlueprintEncodeData(), "label.main") - so_in$BP_encode_fine <- run_singleR(so_in, celldex::BlueprintEncodeData(), "label.fine") - so_in$BP_encode_ont <- run_singleR(so_in, celldex::BlueprintEncodeData()(), "label.ont") - so_in$BP_encode_ont <- cell_ont$name[so_in$BP_encode_ont] - - so_in$monaco_main <- run_singleR(so_in, celldex::MonacoImmuneData(), "label.main") - so_in$monaco_fine <- run_singleR(so_in, celldex::MonacoImmuneData(), "label.fine") - so_in$monaco_ont <- run_singleR(so_in, celldex::MonacoImmuneData(), "label.ont") - so_in$monaco_ont <- cell_ont$name[so_in$monaco_ont] - - so_in$immu_cell_exp_main <- run_singleR( - so_in, - celldex::DatabaseImmuneCellExpressionData(), - "label.main" - ) - so_in$immu_cell_exp_fine <- run_singleR( - so_in, - celldex::DatabaseImmuneCellExpressionData(), - "label.fine" - ) - so_in$immu_cell_exp_ont <- run_singleR( - so_in, - celldex::DatabaseImmuneCellExpressionData(), - "label.ont" -======= so_in$BP_encode_main <- run_singleR( so_in, fetch_celldex_ref("BP_encode"), "label.main" ) @@ -108,7 +68,6 @@ run_singleR_db <- function(so_in, species) { ) so_in$immu_cell_exp_ont <- run_singleR( so_in, fetch_celldex_ref("dice"), "label.ont" ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) ) so_in$immu_cell_exp_ont <- cell_ont$name[so_in$immu_cell_exp_ont] so_in$annot <- so_in$HPCA_main @@ -124,11 +83,6 @@ run_singleR_db <- function(so_in, species) { ) so_in$immgen_ont <- cell_ont$name[so_in$immgen_ont] -<<<<<<< HEAD - so_in$mouseRNAseq_main <- run_singleR(so_in, celldex::MouseRNAseqData(), "label.main") - so_in$mouseRNAseq_fine <- run_singleR(so_in, celldex::MouseRNAseqData(), "label.fine") - so_in$mouseRNAseq_ont <- run_singleR(so_in, celldex::MouseRNAseqData(), "label.ont") -======= so_in$mouseRNAseq_main <- run_singleR( so_in, fetch_celldex_ref("mouseRNAseq"), "label.main" ) @@ -138,7 +92,6 @@ run_singleR_db <- function(so_in, species) { so_in$mouseRNAseq_ont <- run_singleR( so_in, fetch_celldex_ref("mouseRNAseq"), "label.ont" ) ->>>>>>> 6c9f3fa (feat: tests and plotting function updates) so_in$mouseRNAseq_ont <- cell_ont$name[so_in$mouseRNAseq_ont] so_in$annot <- so_in$immgen_main From 40c6ad0638e4714a36a61b9e1d8dc4e6d95d91d7 Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:13:21 -0500 Subject: [PATCH 06/23] Apply suggestions from code review Co-authored-by: Kelly Sovacool, PhD --- R/fetch_celldex_ref.R | 2 -- R/make_bubble_plot.R | 19 +++++++------------ R/make_volcano_plot.R | 6 ++---- R/run_singleR.R | 2 -- R/run_singleR_cluster.R | 6 ++---- R/run_singleR_db.R | 3 --- 6 files changed, 11 insertions(+), 27 deletions(-) diff --git a/R/fetch_celldex_ref.R b/R/fetch_celldex_ref.R index 7ec3aa1..16688d0 100644 --- a/R/fetch_celldex_ref.R +++ b/R/fetch_celldex_ref.R @@ -5,8 +5,6 @@ #' be cache-agnostic by declaring the cache location as the local working #' directory #' -#' @import celldex -#' @import SingleR #' #' @export #' diff --git a/R/make_bubble_plot.R b/R/make_bubble_plot.R index 1ec5350..813169c 100644 --- a/R/make_bubble_plot.R +++ b/R/make_bubble_plot.R @@ -9,11 +9,6 @@ #' @param assay The counts assay to use for determining expression #' @param ident The categorical identity to classify groups of cells #' -#' @import Seurat -#' @import ggplot2 -#' @import dplyr -#' @import reshape2 -#' @import RColorBrewer #' #' @export #' @@ -24,10 +19,10 @@ make_bubble_plot <- function( ) { Idents(so) <- ident - dotplot <- DotPlot(so, features = features) + dotplot <- Seurat::DotPlot(so, features = features) pct_expression <- dplyr::select(dotplot$data, pct.exp, id, features.plot) - avg_expression <- AverageExpression(so, assay = assay, features = features)[[assay]] + avg_expression <- Seurat::AverageExpression(so, assay = assay, features = features)[[assay]] avg_expression <- as.matrix(avg_expression) avg_expression_df <- reshape2::melt(avg_expression) colnames(avg_expression_df) <- c("Gene", "Group", "AvgExp") @@ -40,13 +35,13 @@ make_bubble_plot <- function( )] } - plot <- ggplot(avg_expression_df, aes( + plot <- ggplot2::ggplot(avg_expression_df, ggplot2::aes( x = Group, y = Gene, size = PctExp, color = AvgExp )) + - geom_point() + - scale_color_distiller(palette = palette) + - theme_bw() + - theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1)) + ggplot2::geom_point() + + ggplot2::scale_color_distiller(palette = palette) + + ggplot2::theme_bw() + + ggplot2::theme(axis.text.x = ggplot2::element_text(angle = 45, vjust = 1, hjust = 1)) return(bubble_plot) } diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index e3d4067..955fe8b 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -11,8 +11,6 @@ #' @param label Numeric value of top n genes to label, or a character vector of #' genes to label. Set label to NULL to generate unlabeled plot #' -#' @import ggplot2 -#' @import ggrepel #' #' @export #' @@ -34,10 +32,10 @@ make_volcano_plot <- function( if (logfc == TRUE) { significance[which(abs(de_table$avg_log2FC) > 1.5)] <- "avg_log2FC > 1.5" } - if (pval == TRUE) { + if (isTRUE(pval)) { significance[which(de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05" } - if (significant == T) { + if (isTRUE(significant)) { significance[which(abs(de_table$avg_log2FC) > 1.5 & de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" } df <- as.data.frame(cbind(avg_log2FC, log10_p, significance, gene)) diff --git a/R/run_singleR.R b/R/run_singleR.R index 6ca8b9a..c05a39a 100644 --- a/R/run_singleR.R +++ b/R/run_singleR.R @@ -7,8 +7,6 @@ #' package #' @param label The label identity to be used. Must be a column header in the metadata of `ref_file` #' -#' @import SingleR -#' @import Seurat #' #' @export #' diff --git a/R/run_singleR_cluster.R b/R/run_singleR_cluster.R index a0dd63a..09c18a0 100644 --- a/R/run_singleR_cluster.R +++ b/R/run_singleR_cluster.R @@ -8,8 +8,6 @@ #' (SingleCellExperiment object) #' @param label A cell type label from the metadata column headers #' -#' @import celldex -#' @import SingleR #' #' @export #' @@ -17,10 +15,10 @@ #' clusters #' run_singleR_cluster <- function(so_in, ref_file, label) { - avg <- AverageExpression(so_in, assays = "SCT")$SCT + avg <- Seurat::AverageExpression(so_in, assays = "SCT")$SCT avg <- as.data.frame(avg) ref <- ref_file - s <- SingleR(test = as.matrix(avg), ref = ref, labels = ref[[label]]) + s <- Singler::SingleR(test = as.matrix(avg), ref = ref, labels = ref[[label]]) clust_annot <- s$labels names(clust_annot) <- colnames(avg) diff --git a/R/run_singleR_db.R b/R/run_singleR_db.R index 4568727..8ac574d 100644 --- a/R/run_singleR_db.R +++ b/R/run_singleR_db.R @@ -7,9 +7,6 @@ #' @param species Indicates human (hg19 or hg38) or mouse (mm10) references to #' be used #' -#' @import SingleR -#' @import celldex -#' @import ontoProc #' #' @export #' From ee6cbfb9f66e406ed874c77d0a3344ad1eb0907b Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Tue, 18 Nov 2025 11:28:53 -0500 Subject: [PATCH 07/23] fix: update to correct errors in PR --- .gitignore | 4 +++- DESCRIPTION | 7 +++++-- NAMESPACE | 9 +++++++++ R/filter_doublets.R | 3 --- R/make_bubble_plot.R | 8 ++++---- R/run_AUCell.R | 2 -- man/fetch_celldex_ref.Rd | 17 +++++++++++++++++ man/make_bubble_plot.Rd | 2 +- man/make_volcano_plot.Rd | 13 ++++++++++--- tests/testthat/test-run_singleR.R | 2 +- tests/testthat/test-run_singleR_cluster.R | 3 +++ 11 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 man/fetch_celldex_ref.Rd diff --git a/.gitignore b/.gitignore index 521995b..e0ef58f 100644 --- a/.gitignore +++ b/.gitignore @@ -9,5 +9,7 @@ inst/doc /doc/ /Meta/ /README.html - +bucket +status /.quarto/ +.vscode diff --git a/DESCRIPTION b/DESCRIPTION index 67383d8..71783d4 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -30,13 +30,14 @@ Imports: org.Hs.eg.db, org.Mm.eg.db, Orthology.eg.db, + RColorBrewer, reshape2, rlang, rliger, scDblFinder, Seurat, - SeuratData, - SingleCellExperiment, + SeuratObject, + SeuratWrappers, SingleR, stats, utils @@ -47,6 +48,7 @@ Suggests: ontologyIndex, R.utils, rmarkdown, + SeuratData, SingleCellExperiment, testthat (>= 3.0.0), usethis @@ -54,6 +56,7 @@ Remotes: chris-mcginnis-ucsf/DoubletFinder, rnabioco/djvdj@*release, SeuratWrappers=satijalab/seurat-wrappers + SeuratData=satijalab/seurat-data biocViews: Config/Needs/check: rcmdcheck, lintr, goodpractice Config/testthat/edition: 3 diff --git a/NAMESPACE b/NAMESPACE index 1d1e0eb..64210d3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -9,6 +9,8 @@ export(calc_sc_gsea_score) export(cluster_metrics) export(convert_human_gene_list) export(convert_mtx_to_h5) +export(fetch_celldex_ref) +export(filter_cells) export(filter_doublets) export(make_bubble_plot) export(make_volcano_plot) @@ -23,12 +25,19 @@ export(seurat_clustering) export(split_featurePlot) import(DoubletFinder) import(DropletUtils) +import(RColorBrewer) import(Seurat) import(SeuratWrappers) +import(SingleR) +import(celldex) import(clusterSim) import(djvdj) +import(dplyr) import(ggplot2) +import(ggrepel) import(harmony) +import(ontoProc) +import(reshape2) import(rliger) import(scDblFinder) import(stats) diff --git a/R/filter_doublets.R b/R/filter_doublets.R index a76c3ed..d3b5292 100644 --- a/R/filter_doublets.R +++ b/R/filter_doublets.R @@ -56,7 +56,6 @@ filter_doublets <- function(so_in, doublet_finder_method = "DoubletFinder") { so_in <- subset(so_in, cells = colnames(so_in)[which(so_in$doubletFinder_label == "Singlet")]) } else if (doublet_finder_method == "scDblFinder") { sce <- Seurat::as.SingleCellExperiment(so_in) - set.seed(42) sce_dbl <- scDblFinder(sce) %>% suppressWarnings() so_in$scDblFinder_label <- sce_dbl$scDblFinder.class so_in <- subset(so_in, cells = colnames(so_in)[which(so_in$scDblFinder_label == "singlet")]) @@ -95,7 +94,6 @@ filter_doublets <- function(so_in, doublet_finder_method = "DoubletFinder") { so_in$doubletFinder_label <- dfso[[utils::tail(names(dfso@meta.data), 1)]] sce <- Seurat::as.SingleCellExperiment(so_in) - set.seed(42) sce_dbl <- scDblFinder::scDblFinder(sce) %>% suppressWarnings() so_in$scDblFinder_label <- sce_dbl$scDblFinder.class so_in <- subset(so_in, cells = colnames(so_in)[intersect( @@ -137,7 +135,6 @@ filter_doublets <- function(so_in, doublet_finder_method = "DoubletFinder") { so_in$doubletFinder_label <- dfso[[utils::tail(names(dfso@meta.data), 1)]] sce <- Seurat::as.SingleCellExperiment(so_in) - set.seed(42) sce_dbl <- scDblFinder(sce) %>% suppressWarnings() so_in$scDblFinder_label <- sce_dbl$scDblFinder.class so_in <- subset(so_in, cells = colnames(so_in)[unique(c( diff --git a/R/make_bubble_plot.R b/R/make_bubble_plot.R index 1ec5350..4567446 100644 --- a/R/make_bubble_plot.R +++ b/R/make_bubble_plot.R @@ -24,15 +24,15 @@ make_bubble_plot <- function( ) { Idents(so) <- ident - dotplot <- DotPlot(so, features = features) + dotplot <- Seurat::DotPlot(so, features = features) pct_expression <- dplyr::select(dotplot$data, pct.exp, id, features.plot) - avg_expression <- AverageExpression(so, assay = assay, features = features)[[assay]] + avg_expression <- Seurat::AverageExpression(so, assay = assay, features = features)[[assay]] avg_expression <- as.matrix(avg_expression) avg_expression_df <- reshape2::melt(avg_expression) colnames(avg_expression_df) <- c("Gene", "Group", "AvgExp") avg_expression_df$PctExp <- 0 - avg_expression_df$Group <- as.integer(gsub("[^0-9]", "", avg_expression_df$Group)) + # avg_expression_df$Group <- as.integer(gsub("[^0-9]", "", avg_expression_df$Group)) for (i in seq_len(nrow(avg_expression_df))) { avg_expression_df[i, 4] <- pct_expression$pct.exp[which( pct_expression$id == avg_expression_df[i, "Group"] & @@ -40,7 +40,7 @@ make_bubble_plot <- function( )] } - plot <- ggplot(avg_expression_df, aes( + plot <- ggplot2::ggplot(avg_expression_df, aes( x = Group, y = Gene, size = PctExp, color = AvgExp )) + geom_point() + diff --git a/R/run_AUCell.R b/R/run_AUCell.R index ae51955..a8244be 100644 --- a/R/run_AUCell.R +++ b/R/run_AUCell.R @@ -19,8 +19,6 @@ #' gene set. These values can be added to the original Seurat object ex post #' facto. run_AUCell <- function(so, gene_sets) { - set.seed(42) - # Retrieve normalized counts matrix expr <- Seurat::FetchData( so, diff --git a/man/fetch_celldex_ref.Rd b/man/fetch_celldex_ref.Rd new file mode 100644 index 0000000..4ccbbde --- /dev/null +++ b/man/fetch_celldex_ref.Rd @@ -0,0 +1,17 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_celldex_ref.R +\name{fetch_celldex_ref} +\alias{fetch_celldex_ref} +\title{fetch_celldex_ref: Helper function to import annotation references from +celldex} +\usage{ +fetch_celldex_ref(ref_name) +} +\value{ +A celldex single cell object in SCE data structure +} +\description{ +Retrieves one of the 7 available references in celldex. Should +be cache-agnostic by declaring the cache location as the local working +directory +} diff --git a/man/make_bubble_plot.Rd b/man/make_bubble_plot.Rd index 5e09245..1688601 100644 --- a/man/make_bubble_plot.Rd +++ b/man/make_bubble_plot.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/make_bubble_plot.R \name{make_bubble_plot} \alias{make_bubble_plot} -\title{make a flexible bubble plot with Seurat::DotPlot} +\title{make_bubble_plot: Flexible dotplot} \usage{ make_bubble_plot( so, diff --git a/man/make_volcano_plot.Rd b/man/make_volcano_plot.Rd index d47e419..3f865ea 100644 --- a/man/make_volcano_plot.Rd +++ b/man/make_volcano_plot.Rd @@ -5,17 +5,24 @@ \title{make_volcano_plot: Optimized volcano plot for Seurat differential expression (FindMarkers) output} \usage{ -make_volcano_plot(de_table, significant = TRUE, logfc = TRUE, pval = TRUE) +make_volcano_plot( + de_table, + significant = TRUE, + logfc = TRUE, + pval = TRUE, + label = 50 +) } \arguments{ \item{de_table}{Differential expression table generated by Seurat containing p_val, pct.1, pct.2 avg_log2FC and p_val_adj} -\item{significant}{Boolean to color genes that meet both above thresholds} - \item{logfc}{Boolean to color genes meeting logfc threshold of 1.5} \item{pval}{Boolean to color genes meeting p-value threshold of 0.05} + +\item{label}{Numeric value of top n genes to label, or a character vector of +genes to label. Set label to NULL to generate unlabeled plot} } \value{ Returns a volcano plot as a ggplot2 object diff --git a/tests/testthat/test-run_singleR.R b/tests/testthat/test-run_singleR.R index 69ceee2..80d8b18 100644 --- a/tests/testthat/test-run_singleR.R +++ b/tests/testthat/test-run_singleR.R @@ -5,7 +5,7 @@ test_that("object_size", { test_that("cell_type_annotation", { pbmc <- suppressMessages(import_pbmc()) - + set.seed(42) ref <- fetch_celldex_ref("hpca") singleR_output <- run_singleR(pbmc, ref, "label.main") diff --git a/tests/testthat/test-run_singleR_cluster.R b/tests/testthat/test-run_singleR_cluster.R index 4098a1f..0b836c6 100644 --- a/tests/testthat/test-run_singleR_cluster.R +++ b/tests/testthat/test-run_singleR_cluster.R @@ -1,10 +1,12 @@ test_that("object_size", { pbmc <- suppressMessages(import_pbmc()) + set.seed(42) expect_equal(ncol(pbmc), 2638) }) test_that("cluster_count", { pbmc <- suppressMessages(import_pbmc()) + set.seed(42) expect_equal(length(unique(pbmc$seurat_clusters)), 12) }) @@ -12,6 +14,7 @@ test_that("cluster_cell_annot_type_count", { pbmc <- suppressMessages(import_pbmc()) ref <- fetch_celldex_ref("hpca") Idents(pbmc) <- "seurat_clusters" + set.seed(42) singleR_cluster <- run_singleR_cluster( so_in = pbmc, ref_file = ref, From 0af99b0e9725594ec3cbbe70aa9a3fab33bd1190 Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Tue, 18 Nov 2025 12:04:33 -0500 Subject: [PATCH 08/23] fix: updates for check log --- .Rbuildignore | 5 +++++ DESCRIPTION | 1 - NAMESPACE | 8 -------- R/fetch_celldex_ref.R | 2 ++ R/make_bubble_plot.R | 7 +++++-- R/make_volcano_plot.R | 12 +++++++----- R/run_singleR_cluster.R | 2 +- man/fetch_celldex_ref.Rd | 4 ++++ man/make_volcano_plot.Rd | 3 +++ 9 files changed, 27 insertions(+), 17 deletions(-) diff --git a/.Rbuildignore b/.Rbuildignore index b5369b6..5695465 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -17,3 +17,8 @@ ^Meta$ ^SCOT\.Rproj$ ^README.html$ +^bucket$ +^status$ +^tests/testthat/bucket$ +^tests/testthat/status$ +^\.vscode$ diff --git a/DESCRIPTION b/DESCRIPTION index 71783d4..b9efb73 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -30,7 +30,6 @@ Imports: org.Hs.eg.db, org.Mm.eg.db, Orthology.eg.db, - RColorBrewer, reshape2, rlang, rliger, diff --git a/NAMESPACE b/NAMESPACE index 64210d3..b27e600 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -25,19 +25,11 @@ export(seurat_clustering) export(split_featurePlot) import(DoubletFinder) import(DropletUtils) -import(RColorBrewer) import(Seurat) import(SeuratWrappers) -import(SingleR) -import(celldex) import(clusterSim) import(djvdj) -import(dplyr) -import(ggplot2) -import(ggrepel) import(harmony) -import(ontoProc) -import(reshape2) import(rliger) import(scDblFinder) import(stats) diff --git a/R/fetch_celldex_ref.R b/R/fetch_celldex_ref.R index 16688d0..8a0a573 100644 --- a/R/fetch_celldex_ref.R +++ b/R/fetch_celldex_ref.R @@ -5,6 +5,8 @@ #' be cache-agnostic by declaring the cache location as the local working #' directory #' +#' @param ref_name Character string to be used for retrieving references from +#' the celldex package #' #' @export #' diff --git a/R/make_bubble_plot.R b/R/make_bubble_plot.R index 62b2195..1763915 100644 --- a/R/make_bubble_plot.R +++ b/R/make_bubble_plot.R @@ -17,7 +17,10 @@ make_bubble_plot <- function( so, features, palette = "RdBu", assay = "SCT", ident = "seurat_clusters" ) { - Idents(so) <- ident + pct.exp <- id <- features.plot <- NULL + Group <- Gene <- PctExp <- AvgExp <- NULL + + Seurat::Idents(so) <- ident dotplot <- Seurat::DotPlot(so, features = features) pct_expression <- dplyr::select(dotplot$data, pct.exp, id, features.plot) @@ -35,7 +38,7 @@ make_bubble_plot <- function( )] } - plot <- ggplot2::ggplot(avg_expression_df, ggplot2::aes( + bubble_plot <- ggplot2::ggplot(avg_expression_df, ggplot2::aes( x = Group, y = Gene, size = PctExp, color = AvgExp )) + ggplot2::geom_point() + diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index 955fe8b..8bd433b 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -10,6 +10,8 @@ #' @param pval Boolean to color genes meeting p-value threshold of 0.05 #' @param label Numeric value of top n genes to label, or a character vector of #' genes to label. Set label to NULL to generate unlabeled plot +#' @param significant Numeric value of significant genes to label (top n genes) +#' or character vector of user-specified genes #' #' #' @export @@ -58,15 +60,15 @@ make_volcano_plot <- function( } - volcano <- ggplot(df, aes(x = avg_log2FC, y = log10_p, col = significance)) + - geom_point() + + volcano <- ggplot2::ggplot(df, ggplot2::aes(x = avg_log2FC, y = log10_p, col = significance)) + + ggplot2::geom_point() + # geom_vline(xintercept = 0, color = "black", linewidth = 1.5)+ - xlim(-ceiling(max(abs(df$avg_log2FC))), ceiling(max(abs(df$avg_log2FC)))) + ggplot2::xlim(-ceiling(max(abs(df$avg_log2FC))), ceiling(max(abs(df$avg_log2FC)))) if (!is.null(data_subset)) { volcano <- volcano + - geom_text_repel( - aes(label = gene), + ggrepel::geom_text_repel( + ggplot2::aes(label = gene), data_subset, color = "black", max.overlaps = Inf diff --git a/R/run_singleR_cluster.R b/R/run_singleR_cluster.R index 09c18a0..baaeabd 100644 --- a/R/run_singleR_cluster.R +++ b/R/run_singleR_cluster.R @@ -18,7 +18,7 @@ run_singleR_cluster <- function(so_in, ref_file, label) { avg <- Seurat::AverageExpression(so_in, assays = "SCT")$SCT avg <- as.data.frame(avg) ref <- ref_file - s <- Singler::SingleR(test = as.matrix(avg), ref = ref, labels = ref[[label]]) + s <- SingleR::SingleR(test = as.matrix(avg), ref = ref, labels = ref[[label]]) clust_annot <- s$labels names(clust_annot) <- colnames(avg) diff --git a/man/fetch_celldex_ref.Rd b/man/fetch_celldex_ref.Rd index 4ccbbde..44986b1 100644 --- a/man/fetch_celldex_ref.Rd +++ b/man/fetch_celldex_ref.Rd @@ -7,6 +7,10 @@ celldex} \usage{ fetch_celldex_ref(ref_name) } +\arguments{ +\item{ref_name}{Character string to be used for retrieving references from +the celldex package} +} \value{ A celldex single cell object in SCE data structure } diff --git a/man/make_volcano_plot.Rd b/man/make_volcano_plot.Rd index 3f865ea..45e80ca 100644 --- a/man/make_volcano_plot.Rd +++ b/man/make_volcano_plot.Rd @@ -17,6 +17,9 @@ make_volcano_plot( \item{de_table}{Differential expression table generated by Seurat containing p_val, pct.1, pct.2 avg_log2FC and p_val_adj} +\item{significant}{Numeric value of significant genes to label (top n genes) +or character vector of user-specified genes} + \item{logfc}{Boolean to color genes meeting logfc threshold of 1.5} \item{pval}{Boolean to color genes meeting p-value threshold of 0.05} From 606080d29303ef546221c815edbfbea590f7589b Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Tue, 18 Nov 2025 12:15:04 -0500 Subject: [PATCH 09/23] Update helper.R Using `package::function()` format --- tests/testthat/helper.R | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index cda42d2..3f483c3 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -5,16 +5,16 @@ import_pbmc <- function() { # prepare test dataset pbmc3k <- suppressWarnings(SeuratData::LoadData("pbmc3k")) - pbmc <- UpdateSeuratObject(pbmc3k) + pbmc <- Seurat::UpdateSeuratObject(pbmc3k) set.seed(42) - pbmc[["percent.mt"]] <- PercentageFeatureSet(pbmc, pattern = "^MT-") + pbmc[["percent.mt"]] <- Seurat::PercentageFeatureSet(pbmc, pattern = "^MT-") pbmc <- subset(pbmc, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5 ) - pbmc <- SCTransform(pbmc, vars.to.regress = "percent.mt", verbose = FALSE) - pbmc <- RunPCA(pbmc, features = VariableFeatures(object = pbmc)) - pbmc <- FindNeighbors(pbmc, dims = 1:30) - pbmc <- FindClusters(pbmc, resolution = 0.8, verbose = FALSE) + pbmc <- Seurat::SCTransform(pbmc, vars.to.regress = "percent.mt", verbose = FALSE) + pbmc <- Seurat::RunPCA(pbmc, features = VariableFeatures(object = pbmc)) + pbmc <- Seurat::FindNeighbors(pbmc, dims = 1:30) + pbmc <- Seurat::FindClusters(pbmc, resolution = 0.8, verbose = FALSE) return(pbmc) } From b8ee336f1e480b6e5d2034c7f5ed622027aafd4d Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Tue, 18 Nov 2025 12:16:57 -0500 Subject: [PATCH 10/23] Update R/fetch_celldex_ref.R Co-authored-by: Kelly Sovacool, PhD --- R/fetch_celldex_ref.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/fetch_celldex_ref.R b/R/fetch_celldex_ref.R index 8a0a573..b4b1ad5 100644 --- a/R/fetch_celldex_ref.R +++ b/R/fetch_celldex_ref.R @@ -11,7 +11,7 @@ #' @export #' #' @return A celldex single cell object in SCE data structure -fetch_celldex_ref <- function(ref_name) { +fetch_celldex_ref <- function(ref_name, cache = '.') { ref <- switch(ref_name, "hpca" = , "HumanPrimaryCellAtlasData" = celldex::fetchReference( From 662ab6a683e61860e1df46c3186b530a3aadc0bc Mon Sep 17 00:00:00 2001 From: Kelly Sovacool Date: Tue, 18 Nov 2025 13:39:32 -0500 Subject: [PATCH 11/23] fix: typo --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index b9efb73..dbcb557 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -54,8 +54,8 @@ Suggests: Remotes: chris-mcginnis-ucsf/DoubletFinder, rnabioco/djvdj@*release, + SeuratData=satijalab/seurat-data, SeuratWrappers=satijalab/seurat-wrappers - SeuratData=satijalab/seurat-data biocViews: Config/Needs/check: rcmdcheck, lintr, goodpractice Config/testthat/edition: 3 From dbc23778ba49deea67e7acb1c3b0c7c63ad12930 Mon Sep 17 00:00:00 2001 From: Kelly Sovacool Date: Tue, 18 Nov 2025 14:36:55 -0500 Subject: [PATCH 12/23] chore: document() --- NAMESPACE | 1 - man/fetch_celldex_ref.Rd | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index b27e600..fc8baa3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,7 +10,6 @@ export(cluster_metrics) export(convert_human_gene_list) export(convert_mtx_to_h5) export(fetch_celldex_ref) -export(filter_cells) export(filter_doublets) export(make_bubble_plot) export(make_volcano_plot) diff --git a/man/fetch_celldex_ref.Rd b/man/fetch_celldex_ref.Rd index 44986b1..a4a6d4d 100644 --- a/man/fetch_celldex_ref.Rd +++ b/man/fetch_celldex_ref.Rd @@ -5,7 +5,7 @@ \title{fetch_celldex_ref: Helper function to import annotation references from celldex} \usage{ -fetch_celldex_ref(ref_name) +fetch_celldex_ref(ref_name, cache = ".") } \arguments{ \item{ref_name}{Character string to be used for retrieving references from From 683c85c0e877637c230c581ac63d58d5711a3d9e Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Tue, 18 Nov 2025 16:18:18 -0500 Subject: [PATCH 13/23] fix: documentation; feat: scale in bubble plot --- R/fetch_celldex_ref.R | 3 ++- R/make_bubble_plot.R | 9 +++++++-- R/make_volcano_plot.R | 4 ++-- man/fetch_celldex_ref.Rd | 2 ++ man/make_bubble_plot.Rd | 3 +++ man/make_volcano_plot.Rd | 4 ++-- 6 files changed, 18 insertions(+), 7 deletions(-) diff --git a/R/fetch_celldex_ref.R b/R/fetch_celldex_ref.R index b4b1ad5..59ef987 100644 --- a/R/fetch_celldex_ref.R +++ b/R/fetch_celldex_ref.R @@ -7,11 +7,12 @@ #' #' @param ref_name Character string to be used for retrieving references from #' the celldex package +#' @param cache Character string to identify cache download location #' #' @export #' #' @return A celldex single cell object in SCE data structure -fetch_celldex_ref <- function(ref_name, cache = '.') { +fetch_celldex_ref <- function(ref_name, cache = ".") { ref <- switch(ref_name, "hpca" = , "HumanPrimaryCellAtlasData" = celldex::fetchReference( diff --git a/R/make_bubble_plot.R b/R/make_bubble_plot.R index 1763915..87382f8 100644 --- a/R/make_bubble_plot.R +++ b/R/make_bubble_plot.R @@ -8,14 +8,15 @@ #' @param palette A color palette from ggplot2 #' @param assay The counts assay to use for determining expression #' @param ident The categorical identity to classify groups of cells -#' +#' @param scale Boolean to scale average expression across identities #' #' @export #' #' @return A ggplot2 figure #' make_bubble_plot <- function( - so, features, palette = "RdBu", assay = "SCT", ident = "seurat_clusters" + so, features, palette = "RdBu", assay = "SCT", + scale = FALSE, ident = "seurat_clusters" ) { pct.exp <- id <- features.plot <- NULL Group <- Gene <- PctExp <- AvgExp <- NULL @@ -27,6 +28,10 @@ make_bubble_plot <- function( avg_expression <- Seurat::AverageExpression(so, assay = assay, features = features)[[assay]] avg_expression <- as.matrix(avg_expression) + colnames(avg_expression) <- gsub("-", "_", colnames(avg_expression)) + if (isTRUE(scale)) { + avg_expression <- t(scale(t(avg_expression))) + } avg_expression_df <- reshape2::melt(avg_expression) colnames(avg_expression_df) <- c("Gene", "Group", "AvgExp") avg_expression_df$PctExp <- 0 diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index 8bd433b..26a996b 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -8,10 +8,10 @@ #' p_val, pct.1, pct.2 avg_log2FC and p_val_adj #' @param logfc Boolean to color genes meeting logfc threshold of 1.5 #' @param pval Boolean to color genes meeting p-value threshold of 0.05 +#' @param significant Boolean to color genes that meet both logfc and p-value +#' thresholds #' @param label Numeric value of top n genes to label, or a character vector of #' genes to label. Set label to NULL to generate unlabeled plot -#' @param significant Numeric value of significant genes to label (top n genes) -#' or character vector of user-specified genes #' #' #' @export diff --git a/man/fetch_celldex_ref.Rd b/man/fetch_celldex_ref.Rd index a4a6d4d..3d40bb4 100644 --- a/man/fetch_celldex_ref.Rd +++ b/man/fetch_celldex_ref.Rd @@ -10,6 +10,8 @@ fetch_celldex_ref(ref_name, cache = ".") \arguments{ \item{ref_name}{Character string to be used for retrieving references from the celldex package} + +\item{cache}{Character string to identify cache download location} } \value{ A celldex single cell object in SCE data structure diff --git a/man/make_bubble_plot.Rd b/man/make_bubble_plot.Rd index 1688601..0b88354 100644 --- a/man/make_bubble_plot.Rd +++ b/man/make_bubble_plot.Rd @@ -9,6 +9,7 @@ make_bubble_plot( features, palette = "RdBu", assay = "SCT", + scale = FALSE, ident = "seurat_clusters" ) } @@ -21,6 +22,8 @@ make_bubble_plot( \item{assay}{The counts assay to use for determining expression} +\item{scale}{Boolean to scale average expression across identities} + \item{ident}{The categorical identity to classify groups of cells} } \value{ diff --git a/man/make_volcano_plot.Rd b/man/make_volcano_plot.Rd index 45e80ca..0514456 100644 --- a/man/make_volcano_plot.Rd +++ b/man/make_volcano_plot.Rd @@ -17,8 +17,8 @@ make_volcano_plot( \item{de_table}{Differential expression table generated by Seurat containing p_val, pct.1, pct.2 avg_log2FC and p_val_adj} -\item{significant}{Numeric value of significant genes to label (top n genes) -or character vector of user-specified genes} +\item{significant}{Boolean to color genes that meet both logfc and p-value +thresholds} \item{logfc}{Boolean to color genes meeting logfc threshold of 1.5} From c48a85547255d1c2a8c5f2cc0c87351b970e3ef9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 15:10:19 +0000 Subject: [PATCH 14/23] =?UTF-8?q?ci:=20=F0=9F=A4=96=20auto-format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CITATION.cff | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/CITATION.cff b/CITATION.cff index e0a4628..79a95da 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -208,6 +208,19 @@ references: email: alboukadel.kassambara@gmail.com year: '2025' doi: 10.32614/CRAN.package.ggpubr +- type: software + title: ggrepel + abstract: 'ggrepel: Automatically Position Non-Overlapping Text Labels with ''ggplot2''' + notes: Imports + url: https://ggrepel.slowkow.com/ + repository: https://CRAN.R-project.org/package=ggrepel + authors: + - family-names: Slowikowski + given-names: Kamil + email: kslowikowski@gmail.com + orcid: https://orcid.org/0000-0002-2843-6370 + year: '2025' + doi: 10.32614/CRAN.package.ggrepel - type: software title: grDevices abstract: 'R: A Language and Environment for Statistical Computing' @@ -322,7 +335,7 @@ references: authors: - family-names: Wickham given-names: Hadley - email: h.wickham@gmail.com + email: hadley@posit.co year: '2025' doi: 10.32614/CRAN.package.reshape2 - type: software @@ -597,6 +610,25 @@ references: orcid: https://orcid.org/0000-0003-3925-190X year: '2025' doi: 10.32614/CRAN.package.rmarkdown +- type: software + title: SeuratData + abstract: 'SeuratData: Install and Manage Seurat Datasets' + notes: Suggests + url: http://www.satijalab.org/seurat + authors: + - family-names: Satija + given-names: Rahul + email: rsatija@nygenome.org + orcid: https://orcid.org/0000-0001-9448-8833 + - family-names: Hoffman + given-names: Paul + email: phoffman@nygenome.org + orcid: https://orcid.org/0000-0002-7693-8957 + - family-names: Butler + given-names: Andrew + email: abutler@nygenome.org + orcid: https://orcid.org/0000-0003-3608-0463 + year: '2025' - type: software title: SingleCellExperiment abstract: 'SingleCellExperiment: S4 Classes for Single Cell Data' From 1259d31529f66967ea3f4a1c36e235404c7504c6 Mon Sep 17 00:00:00 2001 From: Kelly Sovacool Date: Wed, 19 Nov 2025 10:57:16 -0500 Subject: [PATCH 15/23] style: fix lint errors https://github.com/CCBR/SCOT/actions/runs/19504260134/job/55826111606\#step:6:12 --- R/make_volcano_plot.R | 4 ++-- tests/testthat/helper.R | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/R/make_volcano_plot.R b/R/make_volcano_plot.R index 26a996b..57f8591 100644 --- a/R/make_volcano_plot.R +++ b/R/make_volcano_plot.R @@ -17,7 +17,6 @@ #' @export #' #' @return Returns a volcano plot as a ggplot2 object - make_volcano_plot <- function( de_table, significant = TRUE, @@ -38,7 +37,8 @@ make_volcano_plot <- function( significance[which(de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05" } if (isTRUE(significant)) { - significance[which(abs(de_table$avg_log2FC) > 1.5 & de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" + significance[which(abs(de_table$avg_log2FC) > 1.5 & + de_table$p_val_adj < 0.05)] <- "p_val_adj < 0.05 & avg_log2FC > 1.5" } df <- as.data.frame(cbind(avg_log2FC, log10_p, significance, gene)) rownames(df) <- rownames(de_table) diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 3f483c3..812e75f 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -1,4 +1,5 @@ import_pbmc <- function() { + nFeature_RNA <- percent.mt <- NULL if (grepl("pbmc3k", SeuratData::InstalledData()[1]) == FALSE) { SeuratData::InstallData("pbmc3k") } From 2bc67c25690833508c1daf4b70b24d2e87f0ac43 Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Fri, 21 Nov 2025 09:11:27 -0500 Subject: [PATCH 16/23] fix: test update --- NAMESPACE | 1 + tests/testthat/test-run_singleR.R | 2 +- tests/testthat/test-run_singleR_cluster.R | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index fc8baa3..b27e600 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,6 +10,7 @@ export(cluster_metrics) export(convert_human_gene_list) export(convert_mtx_to_h5) export(fetch_celldex_ref) +export(filter_cells) export(filter_doublets) export(make_bubble_plot) export(make_volcano_plot) diff --git a/tests/testthat/test-run_singleR.R b/tests/testthat/test-run_singleR.R index 80d8b18..d74a9a8 100644 --- a/tests/testthat/test-run_singleR.R +++ b/tests/testthat/test-run_singleR.R @@ -11,7 +11,7 @@ test_that("cell_type_annotation", { singleR_output <- run_singleR(pbmc, ref, "label.main") expect_equal(length(which(singleR_output == "T_cells")), 1394) - expect_equal(length(which(singleR_output == "B_cell")), 335) + expect_equal(length(which(singleR_output == "B_cell")), 334) expect_equal(length(which(singleR_output == "Monocyte")), 619) expect_equal(length(which(singleR_output == "NK_cell")), 185) }) diff --git a/tests/testthat/test-run_singleR_cluster.R b/tests/testthat/test-run_singleR_cluster.R index 0b836c6..1a08d86 100644 --- a/tests/testthat/test-run_singleR_cluster.R +++ b/tests/testthat/test-run_singleR_cluster.R @@ -21,8 +21,8 @@ test_that("cluster_cell_annot_type_count", { label = "label.main" ) expect_equal(length(unique(singleR_cluster)), 5) - expect_equal(length(which(singleR_cluster == "B_cell")), 346) + expect_equal(length(which(singleR_cluster == "B_cell")), 345) expect_equal(length(which(singleR_cluster == "Monocyte")), 672) - expect_equal(length(which(singleR_cluster == "NK_cell")), 156) + expect_equal(length(which(singleR_cluster == "NK_cell")), 157) expect_equal(length(which(singleR_cluster == "T_cells")), 1452) }) From ddb8400be969f11f0d64d2103027ff9837af9a74 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:10:01 +0000 Subject: [PATCH 17/23] =?UTF-8?q?ci:=20=F0=9F=A4=96=20auto-format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CITATION.cff | 21 +++++++++++++++++++++ DESCRIPTION | 2 +- NAMESPACE | 1 - 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index 79a95da..eb9b993 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -629,6 +629,27 @@ references: email: abutler@nygenome.org orcid: https://orcid.org/0000-0003-3608-0463 year: '2025' +- type: software + title: roxygen2 + abstract: 'roxygen2: In-Line Documentation for R' + notes: Suggests + url: https://roxygen2.r-lib.org/ + repository: https://CRAN.R-project.org/package=roxygen2 + authors: + - family-names: Wickham + given-names: Hadley + email: hadley@posit.co + orcid: https://orcid.org/0000-0003-4757-117X + - family-names: Danenberg + given-names: Peter + email: pcd@roxygen.org + - family-names: Csárdi + given-names: Gábor + email: csardi.gabor@gmail.com + - family-names: Eugster + given-names: Manuel + year: '2025' + doi: 10.32614/CRAN.package.roxygen2 - type: software title: SingleCellExperiment abstract: 'SingleCellExperiment: S4 Classes for Single Cell Data' diff --git a/DESCRIPTION b/DESCRIPTION index 70798e1..7c386a6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -47,8 +47,8 @@ Suggests: ontologyIndex, R.utils, rmarkdown, - SeuratData, roxygen2, + SeuratData, SingleCellExperiment, testthat (>= 3.0.0), usethis diff --git a/NAMESPACE b/NAMESPACE index b27e600..fc8baa3 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -10,7 +10,6 @@ export(cluster_metrics) export(convert_human_gene_list) export(convert_mtx_to_h5) export(fetch_celldex_ref) -export(filter_cells) export(filter_doublets) export(make_bubble_plot) export(make_volcano_plot) From 81f3dbebcac525df580b3b05c7ce2823332f5a5d Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Mon, 1 Dec 2025 16:19:50 -0500 Subject: [PATCH 18/23] fix: use package::function syntax (#25) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: package function calling * Update helper function * ci: 🤖 auto-format --------- Co-authored-by: Kelly Sovacool, PhD Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- CITATION.cff | 38 ++++++++-------- NAMESPACE | 10 ----- R/add_VDJ_metadata.R | 3 -- R/cluster_metrics.R | 1 - R/convert_mtx_to_h5.R | 3 -- R/filter_doublets.R | 7 +-- R/preprocess_sample.R | 9 ++-- R/run_batch_correction.R | 87 +++++++++++++++---------------------- R/run_hypergeometric_test.R | 2 - R/seurat_clustering.R | 12 +++-- tests/testthat/helper.R | 2 +- 11 files changed, 66 insertions(+), 108 deletions(-) diff --git a/CITATION.cff b/CITATION.cff index eb9b993..bb9075c 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -610,25 +610,6 @@ references: orcid: https://orcid.org/0000-0003-3925-190X year: '2025' doi: 10.32614/CRAN.package.rmarkdown -- type: software - title: SeuratData - abstract: 'SeuratData: Install and Manage Seurat Datasets' - notes: Suggests - url: http://www.satijalab.org/seurat - authors: - - family-names: Satija - given-names: Rahul - email: rsatija@nygenome.org - orcid: https://orcid.org/0000-0001-9448-8833 - - family-names: Hoffman - given-names: Paul - email: phoffman@nygenome.org - orcid: https://orcid.org/0000-0002-7693-8957 - - family-names: Butler - given-names: Andrew - email: abutler@nygenome.org - orcid: https://orcid.org/0000-0003-3608-0463 - year: '2025' - type: software title: roxygen2 abstract: 'roxygen2: In-Line Documentation for R' @@ -650,6 +631,25 @@ references: given-names: Manuel year: '2025' doi: 10.32614/CRAN.package.roxygen2 +- type: software + title: SeuratData + abstract: 'SeuratData: Install and Manage Seurat Datasets' + notes: Suggests + url: http://www.satijalab.org/seurat + authors: + - family-names: Satija + given-names: Rahul + email: rsatija@nygenome.org + orcid: https://orcid.org/0000-0001-9448-8833 + - family-names: Hoffman + given-names: Paul + email: phoffman@nygenome.org + orcid: https://orcid.org/0000-0002-7693-8957 + - family-names: Butler + given-names: Andrew + email: abutler@nygenome.org + orcid: https://orcid.org/0000-0003-3608-0463 + year: '2025' - type: software title: SingleCellExperiment abstract: 'SingleCellExperiment: S4 Classes for Single Cell Data' diff --git a/NAMESPACE b/NAMESPACE index fc8baa3..dc099b5 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -22,16 +22,6 @@ export(run_singleR_cluster) export(run_singleR_db) export(seurat_clustering) export(split_featurePlot) -import(DoubletFinder) -import(DropletUtils) -import(Seurat) -import(SeuratWrappers) -import(clusterSim) -import(djvdj) -import(harmony) -import(rliger) -import(scDblFinder) -import(stats) importFrom(dplyr,"%>%") importFrom(magrittr,"%<>%") importFrom(rlang,":=") diff --git a/R/add_VDJ_metadata.R b/R/add_VDJ_metadata.R index 9f5f362..7ebd129 100644 --- a/R/add_VDJ_metadata.R +++ b/R/add_VDJ_metadata.R @@ -7,9 +7,6 @@ #' @param so A Seurat single cell RNA object #' @param vdj_file A path to a V(D)J annotation directory from CellRanger #' -#' @import djvdj -#' @import Seurat -#' #' @export #' #' @return A Seurat object with V(D)J metadata diff --git a/R/cluster_metrics.R b/R/cluster_metrics.R index 6f40b51..e7f7bf9 100644 --- a/R/cluster_metrics.R +++ b/R/cluster_metrics.R @@ -26,7 +26,6 @@ #' #' @export #' -#' @import clusterSim cluster_metrics <- function(so, cluster_list, dims = 1:20, diff --git a/R/convert_mtx_to_h5.R b/R/convert_mtx_to_h5.R index 65ac03e..02418fa 100644 --- a/R/convert_mtx_to_h5.R +++ b/R/convert_mtx_to_h5.R @@ -17,9 +17,6 @@ #' @param barcodes_file Path to the barcodes.tsv.gz file #' @param features_file Path to the features.tsv.gz file #' -#' @import DropletUtils -#' @import Seurat -#' #' @export convert_mtx_to_h5 <- function(sample_name, mtx_file, diff --git a/R/filter_doublets.R b/R/filter_doublets.R index d3b5292..b1e46a3 100644 --- a/R/filter_doublets.R +++ b/R/filter_doublets.R @@ -13,9 +13,6 @@ #' "DoubletFinder" (default), "scDblFinder", "consensus" removal of doublets, #' or the "union" of total doublets identified in both algorithms #' -#' @import DoubletFinder -#' @import scDblFinder -#' #' @export #' #' @return A subsetted Seurat object with doublets removed @@ -56,7 +53,7 @@ filter_doublets <- function(so_in, doublet_finder_method = "DoubletFinder") { so_in <- subset(so_in, cells = colnames(so_in)[which(so_in$doubletFinder_label == "Singlet")]) } else if (doublet_finder_method == "scDblFinder") { sce <- Seurat::as.SingleCellExperiment(so_in) - sce_dbl <- scDblFinder(sce) %>% suppressWarnings() + sce_dbl <- scDblFinder::scDblFinder(sce) %>% suppressWarnings() so_in$scDblFinder_label <- sce_dbl$scDblFinder.class so_in <- subset(so_in, cells = colnames(so_in)[which(so_in$scDblFinder_label == "singlet")]) } else if (doublet_finder_method == "union") { @@ -135,7 +132,7 @@ filter_doublets <- function(so_in, doublet_finder_method = "DoubletFinder") { so_in$doubletFinder_label <- dfso[[utils::tail(names(dfso@meta.data), 1)]] sce <- Seurat::as.SingleCellExperiment(so_in) - sce_dbl <- scDblFinder(sce) %>% suppressWarnings() + sce_dbl <- scDblFinder::scDblFinder(sce) %>% suppressWarnings() so_in$scDblFinder_label <- sce_dbl$scDblFinder.class so_in <- subset(so_in, cells = colnames(so_in)[unique(c( which(so_in$doubletFinder_label == "Singlet"), diff --git a/R/preprocess_sample.R b/R/preprocess_sample.R index 7e9ed8e..395ec5d 100644 --- a/R/preprocess_sample.R +++ b/R/preprocess_sample.R @@ -15,7 +15,6 @@ #' @param npcs_in Number of principal components to use for dimensionality #' reduction #' -#' @import Seurat #' #' @export #' @@ -32,20 +31,20 @@ preprocess_sample <- function(so_in, species, npcs_in) { } # process - so_1 <- NormalizeData( + so_1 <- Seurat::NormalizeData( so_in, normalization.method = "LogNormalize", scale.factor = 10000, assay = "RNA" ) - so_2 <- ScaleData(so_1, assay = "RNA") - so_3 <- CellCycleScoring( + so_2 <- Seurat::ScaleData(so_1, assay = "RNA") + so_3 <- Seurat::CellCycleScoring( so_2, s.features = s.genes, g2m.features = g2m.genes, set.ident = TRUE ) - so_4 <- SCTransform(so_3) + so_4 <- Seurat::SCTransform(so_3) so_out <- seurat_clustering(so_4, npcs_in) return(so_out) } diff --git a/R/run_batch_correction.R b/R/run_batch_correction.R index 0f2a493..a51d4d1 100644 --- a/R/run_batch_correction.R +++ b/R/run_batch_correction.R @@ -34,11 +34,6 @@ #' @param conda_env A character string for indicating which conda environment #' contains the necessary packages #' -#' @import Seurat -#' @import SeuratWrappers -#' @import harmony -#' @import rliger -#' #' @export #' #' @return A batch corrected Seurat object with updated UMAP projections and @@ -59,7 +54,7 @@ run_batch_correction <- function(so_in, # TODO recommend using package::function syntax instead of importing entire packages # set assay to RNA to avoid double transform/normalization - DefaultAssay(so_in) <- "RNA" + SeuratData::DefaultAssay(so_in) <- "RNA" # integration method for ### SCVI @@ -68,12 +63,12 @@ run_batch_correction <- function(so_in, if (method_in == "scVIIntegration") { message("--running SCVI integration") - so_transform <- NormalizeData(so_in) - so_variable <- FindVariableFeatures(so_transform) - so_scaled <- ScaleData(so_variable) - so_pca <- RunPCA(so_scaled) + so_transform <- Seurat::NormalizeData(so_in) + so_variable <- Seurat::FindVariableFeatures(so_transform) + so_scaled <- Seurat::ScaleData(so_variable) + so_pca <- Seurat::RunPCA(so_scaled) - so_integrate <- IntegrateLayers( + so_integrate <- Seurat::IntegrateLayers( object = so_pca, method = scVIIntegration, new.reduction = "integrated.scvi", @@ -84,21 +79,21 @@ run_batch_correction <- function(so_in, message("--running LIGER") # preprocess - so_norm <- NormalizeData(so_in) - so_norm <- FindVariableFeatures(so_norm) - so_norm <- ScaleData(so_norm, do.center = FALSE) - so_norm <- RunOptimizeALS(so_norm, k = npcs, lambda = 5) - so_integrate <- RunQuantileNorm(so_norm) + so_norm <- Seurat::NormalizeData(so_in) + so_norm <- Seurat::FindVariableFeatures(so_norm) + so_norm <- Seurat::ScaleData(so_norm, do.center = FALSE) + so_norm <- SeuratWrappers::RunOptimizeALS(so_norm, k = npcs, lambda = 5) + so_integrate <- SeuratWrappers::RunQuantileNorm(so_norm) } else { message("--running SCT") # vars.to.regress is NULL by default - so_transform <- SCTransform(so_in, vars.to.regress = v_list) + so_transform <- Seurat::SCTransform(so_in, vars.to.regress = v_list) # runPCA - so_pca <- RunPCA(so_transform) + so_pca <- Seurat::RunPCA(so_transform) - so_integrate <- IntegrateLayers( + so_integrate <- Seurat::IntegrateLayers( object = so_pca, method = get(method_in), normalization.method = "SCT", @@ -108,54 +103,42 @@ run_batch_correction <- function(so_in, } # run neighbors, clusters - so <- FindNeighbors(so_integrate, reduction = reduction_in, dims = 1:npcs) + so <- Seurat::FindNeighbors(so_integrate, reduction = reduction_in, dims = 1:npcs) for (res in resolution_list) { - so <- FindClusters(so, resolution = res, algorithm = 3) + so <- Seurat::FindClusters(so, resolution = res, algorithm = 3) } # reduction - so <- RunUMAP(so, reduction = reduction_in, dims = 1:npcs) + so <- Seurat::RunUMAP(so, reduction = reduction_in, dims = 1:npcs) # add cluster-based annotations cell_ont <- ontoProc::getOnto("cellOnto") if (species == "hg38" || species == "hg19") { - so$clustAnnot_HPCA_main <- run_singleR_cluster(so, celldex::HumanPrimaryCellAtlasData(), "label.main") - so$clustAnnot_HPCA_fine <- run_singleR_cluster(so, celldex::HumanPrimaryCellAtlasData(), "label.fine") - so$clustAnnot_HPCA_ont <- run_singleR_cluster(so, celldex::HumanPrimaryCellAtlasData(), "label.ont") + so$clustAnnot_HPCA_main <- run_singleR_cluster(so, fetch_celldex_ref("hpca"), "label.main") + so$clustAnnot_HPCA_fine <- run_singleR_cluster(so, fetch_celldex_ref("hpca"), "label.fine") + so$clustAnnot_HPCA_ont <- run_singleR_cluster(so, fetch_celldex_ref("hpca"), "label.ont") so$clustAnnot_HPCA_ont <- cell_ont$name[so$clustAnnot_HPCA_ont] - so$clustAnnot_BP_encode_main <- run_singleR_cluster(so, celldex::BlueprintEncodeData(), "label.main") - so$clustAnnot_BP_encode_fine <- run_singleR_cluster(so, celldex::BlueprintEncodeData(), "label.fine") - so$clustAnnot_BP_encode_ont <- run_singleR_cluster(so, celldex::BlueprintEncodeData(), "label.ont") + so$clustAnnot_BP_encode_main <- run_singleR_cluster(so, fetch_celldex_ref("BP_encode"), "label.main") + so$clustAnnot_BP_encode_fine <- run_singleR_cluster(so, fetch_celldex_ref("BP_encode"), "label.fine") + so$clustAnnot_BP_encode_ont <- run_singleR_cluster(so, fetch_celldex_ref("BP_encode"), "label.ont") so$clustAnnot_BP_encode_ont <- cell_ont$name[so$clustAnnot_BP_encode_ont] - so$clustAnnot_monaco_main <- run_singleR_cluster(so, celldex::MonacoImmuneData(), "label.main") - so$clustAnnot_monaco_fine <- run_singleR_cluster(so, celldex::MonacoImmuneData(), "label.fine") - so$clustAnnot_monaco_ont <- run_singleR_cluster(so, celldex::MonacoImmuneData(), "label.ont") + so$clustAnnot_monaco_main <- run_singleR_cluster(so, fetch_celldex_ref("monaco"), "label.main") + so$clustAnnot_monaco_fine <- run_singleR_cluster(so, fetch_celldex_ref("monaco"), "label.fine") + so$clustAnnot_monaco_ont <- run_singleR_cluster(so, fetch_celldex_ref("monaco"), "label.ont") so$clustAnnot_monaco_ont <- cell_ont$name[so$clustAnnot_monaco_ont] - so$clustAnnot_immu_cell_exp_main <- run_singleR_cluster( - so, - celldex::DatabaseImmuneCellExpressionData(), - "label.main" - ) - so$clustAnnot_immu_cell_exp_fine <- run_singleR_cluster( - so, - celldex::DatabaseImmuneCellExpressionData(), - "label.fine" - ) - so$clustAnnot_immu_cell_exp_ont <- run_singleR_cluster( - so, - celldex::DatabaseImmuneCellExpressionData(), - "label.ont" - ) + so$clustAnnot_immu_cell_exp_main <- run_singleR_cluster(so,fetch_celldex_ref("dice"),"label.main") + so$clustAnnot_immu_cell_exp_fine <- run_singleR_cluster(so, fetch_celldex_ref("dice"), "label.fine") + so$clustAnnot_immu_cell_exp_ont <- run_singleR_cluster(so, fetch_celldex_ref("dice"), "label.ont") so$clustAnnot_immu_cell_exp_ont <- cell_ont$name[so$clustAnnot_immu_cell_exp_ont] } else if (species == "mm10") { - so$clustAnnot_immgen_main <- run_singleR_cluster(so, celldex::ImmGenData(), "label.main") - so$clustAnnot_immgen_fine <- run_singleR_cluster(so, celldex::ImmGenData(), "label.fine") - so$clustAnnot_immgen_ont <- run_singleR_cluster(so, celldex::ImmGenData(), "label.ont") + so$clustAnnot_immgen_main <- run_singleR_cluster(so, fetch_celldex_ref("immgen"), "label.main") + so$clustAnnot_immgen_fine <- run_singleR_cluster(so, fetch_celldex_ref("immgen"), "label.fine") + so$clustAnnot_immgen_ont <- run_singleR_cluster(so, fetch_celldex_ref("immgen"), "label.ont") so$clustAnnot_immgen_ont <- cell_ont$name[so$clustAnnot_immgen_ont] - so$clustAnnot_mouseRNAseq_main <- run_singleR_cluster(so, celldex::MouseRNAseqData(), "label.main") - so$clustAnnot_mouseRNAseq_fine <- run_singleR_cluster(so, celldex::MouseRNAseqData(), "label.fine") - so$clustAnnot_mouseRNAseq_ont <- run_singleR_cluster(so, celldex::MouseRNAseqData(), "label.ont") + so$clustAnnot_mouseRNAseq_main <- run_singleR_cluster(so, fetch_celldex_ref("mouseRNAseq"), "label.main") + so$clustAnnot_mouseRNAseq_fine <- run_singleR_cluster(so, fetch_celldex_ref("mouseRNAseq"), "label.fine") + so$clustAnnot_mouseRNAseq_ont <- run_singleR_cluster(so, fetch_celldex_ref("mouseRNAseq"), "label.ont") so$clustAnnot_mouseRNAseq_ont <- cell_ont$name[so$clustAnnot_mouseRNAseq_ont] } return(so) diff --git a/R/run_hypergeometric_test.R b/R/run_hypergeometric_test.R index 448d892..b0b5de8 100644 --- a/R/run_hypergeometric_test.R +++ b/R/run_hypergeometric_test.R @@ -16,8 +16,6 @@ #' @param lowerTail Calculates the p-value as likelihood of being in the upper #' tail (default) or the lower tail of the distribution #' -#' @import stats -#' #' @export #' #' @return Returns a vector with the relevant statistics used to generate the diff --git a/R/seurat_clustering.R b/R/seurat_clustering.R index d7dd5e9..439a3d9 100644 --- a/R/seurat_clustering.R +++ b/R/seurat_clustering.R @@ -10,8 +10,6 @@ #' @param algorithm A value of 1 (Louvain), 2 (Leiden), or 3 (Slow Local Moving #' (SLM)) to select the clustering algorithm (Default 3) #' -#' @import Seurat -#' #' @export #' #' @return The updated Seurat single cell object with recalculated PCA, @@ -20,18 +18,18 @@ seurat_clustering <- function(so_in, npcs_in, resolution = 0.8, algorithm = 3) { - so <- RunPCA( + so <- Seurat::RunPCA( object = so_in, - features = VariableFeatures(object = so_in), + features = Seurat::VariableFeatures(object = so_in), verbose = FALSE, npcs = 50 ) - so <- FindNeighbors(so, dims = 1:npcs_in) - so <- FindClusters(so, + so <- Seurat::FindNeighbors(so, dims = 1:npcs_in) + so <- Seurat::FindClusters(so, resolution = 0.8, algorithm = 3, verbose = TRUE ) - so <- RunUMAP(so, dims = 1:npcs_in, n.components = 3) + so <- Seurat::RunUMAP(so, dims = 1:npcs_in, n.components = 3) return(so) } diff --git a/tests/testthat/helper.R b/tests/testthat/helper.R index 812e75f..6e7afab 100644 --- a/tests/testthat/helper.R +++ b/tests/testthat/helper.R @@ -13,7 +13,7 @@ import_pbmc <- function() { subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5 ) pbmc <- Seurat::SCTransform(pbmc, vars.to.regress = "percent.mt", verbose = FALSE) - pbmc <- Seurat::RunPCA(pbmc, features = VariableFeatures(object = pbmc)) + pbmc <- Seurat::RunPCA(pbmc, features = Seurat::VariableFeatures(object = pbmc)) pbmc <- Seurat::FindNeighbors(pbmc, dims = 1:30) pbmc <- Seurat::FindClusters(pbmc, resolution = 0.8, verbose = FALSE) From 5ef40f1b3b17c36ed8843cfe97ab3be41c017dde Mon Sep 17 00:00:00 2001 From: Nathan W <38703762+wong-nw@users.noreply.github.com> Date: Tue, 2 Dec 2025 12:10:50 -0500 Subject: [PATCH 19/23] Update test-run_singleR_cluster.R Corrects issue with `Idents` function --- tests/testthat/test-run_singleR_cluster.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-run_singleR_cluster.R b/tests/testthat/test-run_singleR_cluster.R index 1a08d86..2b58637 100644 --- a/tests/testthat/test-run_singleR_cluster.R +++ b/tests/testthat/test-run_singleR_cluster.R @@ -13,7 +13,7 @@ test_that("cluster_count", { test_that("cluster_cell_annot_type_count", { pbmc <- suppressMessages(import_pbmc()) ref <- fetch_celldex_ref("hpca") - Idents(pbmc) <- "seurat_clusters" + Seurat::Idents(pbmc) <- "seurat_clusters" set.seed(42) singleR_cluster <- run_singleR_cluster( so_in = pbmc, From 59641480913b674ee41c0f482f20c2531974b40d Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Fri, 5 Dec 2025 10:36:53 -0500 Subject: [PATCH 20/23] fix: unit tests with tolerances added --- tests/testthat/test-run_singleR.R | 8 ++++---- tests/testthat/test-run_singleR_cluster.R | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/testthat/test-run_singleR.R b/tests/testthat/test-run_singleR.R index d74a9a8..33807e3 100644 --- a/tests/testthat/test-run_singleR.R +++ b/tests/testthat/test-run_singleR.R @@ -10,8 +10,8 @@ test_that("cell_type_annotation", { singleR_output <- run_singleR(pbmc, ref, "label.main") - expect_equal(length(which(singleR_output == "T_cells")), 1394) - expect_equal(length(which(singleR_output == "B_cell")), 334) - expect_equal(length(which(singleR_output == "Monocyte")), 619) - expect_equal(length(which(singleR_output == "NK_cell")), 185) + expect_equal(length(which(singleR_output == "T_cells")), 1394, tolerance = 5) + expect_equal(length(which(singleR_output == "B_cell")), 334, tolerance = 5) + expect_equal(length(which(singleR_output == "Monocyte")), 619, tolerance = 5) + expect_equal(length(which(singleR_output == "NK_cell")), 185, tolerance = 5) }) diff --git a/tests/testthat/test-run_singleR_cluster.R b/tests/testthat/test-run_singleR_cluster.R index 2b58637..90b7e52 100644 --- a/tests/testthat/test-run_singleR_cluster.R +++ b/tests/testthat/test-run_singleR_cluster.R @@ -21,8 +21,8 @@ test_that("cluster_cell_annot_type_count", { label = "label.main" ) expect_equal(length(unique(singleR_cluster)), 5) - expect_equal(length(which(singleR_cluster == "B_cell")), 345) - expect_equal(length(which(singleR_cluster == "Monocyte")), 672) - expect_equal(length(which(singleR_cluster == "NK_cell")), 157) - expect_equal(length(which(singleR_cluster == "T_cells")), 1452) + expect_equal(length(which(singleR_cluster == "B_cell")), 345, tolerance = 5) + expect_equal(length(which(singleR_cluster == "Monocyte")), 672, tolerance = 5) + expect_equal(length(which(singleR_cluster == "NK_cell")), 157, tolerance = 5) + expect_equal(length(which(singleR_cluster == "T_cells")), 1452, tolerance = 5) }) From df149e9e9bffa3d2e7ebc037e4b877f32e219388 Mon Sep 17 00:00:00 2001 From: Nathan Wong Date: Fri, 5 Dec 2025 16:01:16 -0500 Subject: [PATCH 21/23] fix: package::function notation implemented --- R/cluster_metrics.R | 2 +- R/run_batch_correction.R | 6 +++--- R/run_hypergeometric_test.R | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/R/cluster_metrics.R b/R/cluster_metrics.R index e7f7bf9..245ff21 100644 --- a/R/cluster_metrics.R +++ b/R/cluster_metrics.R @@ -39,7 +39,7 @@ cluster_metrics <- function(so, silhouette <- FALSE } if (silhouette == TRUE) { - distance <- dist(embed_mat) + distance <- stats::dist(embed_mat) cluster_scores <- cbind(cluster_scores, vector(length = length(cluster_list))) colnames(cluster_scores)[3] <- "Silhouette" } diff --git a/R/run_batch_correction.R b/R/run_batch_correction.R index a51d4d1..d8c6cd1 100644 --- a/R/run_batch_correction.R +++ b/R/run_batch_correction.R @@ -54,7 +54,7 @@ run_batch_correction <- function(so_in, # TODO recommend using package::function syntax instead of importing entire packages # set assay to RNA to avoid double transform/normalization - SeuratData::DefaultAssay(so_in) <- "RNA" + SeuratObject::DefaultAssay(so_in) <- "RNA" # integration method for ### SCVI @@ -70,7 +70,7 @@ run_batch_correction <- function(so_in, so_integrate <- Seurat::IntegrateLayers( object = so_pca, - method = scVIIntegration, + method = SeuratWrappers::scVIIntegration, new.reduction = "integrated.scvi", conda_env = conda_env, dims = 1:npcs @@ -127,7 +127,7 @@ run_batch_correction <- function(so_in, so$clustAnnot_monaco_fine <- run_singleR_cluster(so, fetch_celldex_ref("monaco"), "label.fine") so$clustAnnot_monaco_ont <- run_singleR_cluster(so, fetch_celldex_ref("monaco"), "label.ont") so$clustAnnot_monaco_ont <- cell_ont$name[so$clustAnnot_monaco_ont] - so$clustAnnot_immu_cell_exp_main <- run_singleR_cluster(so,fetch_celldex_ref("dice"),"label.main") + so$clustAnnot_immu_cell_exp_main <- run_singleR_cluster(so, fetch_celldex_ref("dice"), "label.main") so$clustAnnot_immu_cell_exp_fine <- run_singleR_cluster(so, fetch_celldex_ref("dice"), "label.fine") so$clustAnnot_immu_cell_exp_ont <- run_singleR_cluster(so, fetch_celldex_ref("dice"), "label.ont") so$clustAnnot_immu_cell_exp_ont <- cell_ont$name[so$clustAnnot_immu_cell_exp_ont] diff --git a/R/run_hypergeometric_test.R b/R/run_hypergeometric_test.R index b0b5de8..7e0401f 100644 --- a/R/run_hypergeometric_test.R +++ b/R/run_hypergeometric_test.R @@ -32,7 +32,7 @@ run_hypergeometric_test <- function(selectedVect, pVal <- 1 if (inter.size > 0) { - pVal <- phyper( + pVal <- stats::phyper( q = inter.size, m = ref.size, n = nonref.size, From f9ad6ec0048c029a77de32e9dd695833d734afda Mon Sep 17 00:00:00 2001 From: Kelly Sovacool Date: Fri, 5 Dec 2025 16:19:23 -0500 Subject: [PATCH 22/23] fix: use Imports needed by Seurat --- R/reexports.R | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/R/reexports.R b/R/reexports.R index e81ba52..8a54209 100644 --- a/R/reexports.R +++ b/R/reexports.R @@ -17,3 +17,11 @@ rlang::`:=` #' @importFrom rlang .data #' @export rlang::.data + + +# Suppress R CMD check note 'All declared Imports should be used'. +# These packages are used by Seurat, but are only listed in Seurat's Suggests field. +# See \url{https://community.rstudio.com/t/how-should-a-meta-package-handle-this-note-all-declared-imports-should-be-used/23400/3} +#' @importFrom harmony RunHarmony +#' @importFrom rliger createLiger +NULL From 04144473ecd1732007b2807dce9895b2577aaa99 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 5 Dec 2025 22:23:14 +0000 Subject: [PATCH 23/23] =?UTF-8?q?ci:=20=F0=9F=A4=96=20auto-format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- NAMESPACE | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NAMESPACE b/NAMESPACE index dc099b5..307ab09 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -23,6 +23,8 @@ export(run_singleR_db) export(seurat_clustering) export(split_featurePlot) importFrom(dplyr,"%>%") +importFrom(harmony,RunHarmony) importFrom(magrittr,"%<>%") importFrom(rlang,":=") importFrom(rlang,.data) +importFrom(rliger,createLiger)