| Title: | Adaptive Detection of Human-Mouse Multiplets in PDX Single-Cell Data |
|---|---|
| Description: | Detects human-mouse multiplets in patient-derived xenograft (PDX) single-cell RNA-seq data using an adaptive threshold method that does not assume a fixed species proportion. Takes a 10x CellRanger GEM classification file and returns the data with added multiplet classifications, with optional diagnostic plots and helpers to annotate a Seurat or SingleCellExperiment object with multiplet classifications or remove multiplets from it. |
| Authors: | Alexandra Gerveni [aut, cre] (ORCID: <https://orcid.org/0009-0004-5428-5889>) |
| Maintainer: | Alexandra Gerveni <[email protected]> |
| License: | MIT + file LICENSE |
| Version: | 0.99.0 |
| Built: | 2026-07-16 20:40:08 UTC |
| Source: | https://github.com/BiocStaging/multipletR |
Reads a 10x CellRanger GEM classification file, applies the adaptive threshold method to identify human-mouse multiplets without assuming a fixed species proportion, and writes the input data back out with added classification columns. Optionally produces diagnostic plots.
detect_multiplets( fileIn, fileOut, T1 = 70, T2 = 30, T3 = 25, plotPercent = TRUE, plotTotalReads = FALSE, overlapDrop = 10, modeDiff = 0.9, verbose = FALSE )detect_multiplets( fileIn, fileOut, T1 = 70, T2 = 30, T3 = 25, plotPercent = TRUE, plotTotalReads = FALSE, overlapDrop = 10, modeDiff = 0.9, verbose = FALSE )
fileIn |
Path to the input GEM classification CSV (from 10x CellRanger). Expected columns: a barcode column, a human read-count column (GRCh38), a mouse read-count column (e.g. GRCm39 / mm10 / mm39 / mouse_reads), and a 10x call column. |
fileOut |
Path to write the output CSV. The output is the input data with added columns: our_classification (Multiplet / Singlet), pct_human, and pct_mouse. |
T1 |
Upper percent-mouse threshold: the starting upper bound on percent mouse content. Cells above this are too mouse-heavy. Default 70. |
T2 |
Lower percent-mouse threshold: the starting lower bound on percent mouse content (equivalently, the percent-human side). Cells below this are too human-heavy. Default 30. |
T3 |
Total-reads threshold: the starting lower bound on total reads, given as a percentile of the total-reads range (e.g. 25 = 25th percentile). Default 25. |
plotPercent |
Logical, whether to draw the two percent plots (one for the original 10x classification, one for our classification), total reads vs percent mouse. Default TRUE. |
plotTotalReads |
Logical, whether to draw the total-reads plots (mouse reads vs human reads, colored by 10x and our classification). Default FALSE. |
overlapDrop |
Stop expanding a threshold when the overlap between the human and mouse read distributions drops by more than this percentage from its running peak. Lower values are more conservative. Default 10. |
modeDiff |
Stop expanding when the difference between the human and mouse distribution modes increases by more than this amount from the previous step. Default 0.9. |
verbose |
Logical, print the full step-by-step algorithm trace. The final thresholds and multiplet count are always printed; verbose adds the detailed expansion log. Default FALSE. |
The three starting thresholds T1, T2 and T3 follow the notation used in the manuscript. They define the conservative starting region that is then expanded adaptively; the defaults are the values we recommend and they rarely need to be changed.
Invisibly, a data frame: the input data with added columns
our_classification, pct_human, and pct_mouse. Also written to fileOut.
# Detect multiplets in the bundled example PDX dataset (sample PC65) gem_file <- system.file("extdata", "PC65_gem_classification.csv", package = "multipletR" ) res <- detect_multiplets(gem_file, tempfile(fileext = ".csv"), plotPercent = FALSE, plotTotalReads = FALSE ) table(res$our_classification)# Detect multiplets in the bundled example PDX dataset (sample PC65) gem_file <- system.file("extdata", "PC65_gem_classification.csv", package = "multipletR" ) res <- detect_multiplets(gem_file, tempfile(fileext = ".csv"), plotPercent = FALSE, plotTotalReads = FALSE ) table(res$our_classification)
Adds multipletR's per-cell classification to a single-cell object's cell
metadata and, by default, removes the detected multiplets so the object is
ready for downstream analysis. Set remove = FALSE to keep all cells and
only annotate them (useful for visualizing where the multiplets fall, e.g. on
a UMAP colored by multipletR_class before deciding whether to filter).
Works with both Seurat objects and SingleCellExperiment objects; use
the object argument to indicate which one you are passing.
remove_multiplets( x, multiplets, object = c("seurat", "sce"), remove = TRUE, barcode_col = "barcode" )remove_multiplets( x, multiplets, object = c("seurat", "sce"), remove = TRUE, barcode_col = "barcode" )
x |
A single-cell object whose cell names ( |
multiplets |
The data frame returned by |
object |
Which kind of object |
remove |
Logical. If |
barcode_col |
Name of the barcode column in |
The classification follows the same idea as doublet-detection tools such as DoubletFinder: each cell is labeled Human, Mouse, or Multiplet, and the percent human / percent mouse are added per cell.
The input object with three added cell-metadata columns
(multipletR_class, multipletR_pct_human,
multipletR_pct_mouse). If remove = TRUE, the multiplet cells
are also dropped.
# Detect multiplets in the bundled example dataset gem_file <- system.file("extdata", "PC65_gem_classification.csv", package = "multipletR" ) res <- detect_multiplets(gem_file, tempfile(fileext = ".csv"), plotPercent = FALSE, plotTotalReads = FALSE ) # Build a minimal Seurat object whose cell names are the same barcodes counts <- matrix(rpois(20 * nrow(res), 5), nrow = 20, dimnames = list(paste0("gene", 1:20), res$barcode) ) seu <- Seurat::CreateSeuratObject(counts) # Annotate only (keep all cells), e.g. to visualize before filtering seu <- remove_multiplets(seu, res, object = "seurat", remove = FALSE) table(seu$multipletR_class) # Or annotate and remove the multiplets in one step seu_clean <- remove_multiplets(seu, res, object = "seurat")# Detect multiplets in the bundled example dataset gem_file <- system.file("extdata", "PC65_gem_classification.csv", package = "multipletR" ) res <- detect_multiplets(gem_file, tempfile(fileext = ".csv"), plotPercent = FALSE, plotTotalReads = FALSE ) # Build a minimal Seurat object whose cell names are the same barcodes counts <- matrix(rpois(20 * nrow(res), 5), nrow = 20, dimnames = list(paste0("gene", 1:20), res$barcode) ) seu <- Seurat::CreateSeuratObject(counts) # Annotate only (keep all cells), e.g. to visualize before filtering seu <- remove_multiplets(seu, res, object = "seurat", remove = FALSE) table(seu$multipletR_class) # Or annotate and remove the multiplets in one step seu_clean <- remove_multiplets(seu, res, object = "seurat")