Package 'multipletR'

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

Help Index


Detect human-mouse multiplets in PDX single-cell data

Description

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.

Usage

detect_multiplets(
  fileIn,
  fileOut,
  T1 = 70,
  T2 = 30,
  T3 = 25,
  plotPercent = TRUE,
  plotTotalReads = FALSE,
  overlapDrop = 10,
  modeDiff = 0.9,
  verbose = FALSE
)

Arguments

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.

Details

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.

Value

Invisibly, a data frame: the input data with added columns our_classification, pct_human, and pct_mouse. Also written to fileOut.

Examples

# 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)

Annotate (and optionally remove) multiplets in a Seurat or SingleCellExperiment object

Description

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.

Usage

remove_multiplets(
  x,
  multiplets,
  object = c("seurat", "sce"),
  remove = TRUE,
  barcode_col = "barcode"
)

Arguments

x

A single-cell object whose cell names (colnames) are barcodes: either a Seurat object or a SingleCellExperiment.

multiplets

The data frame returned by detect_multiplets (must contain barcode, our_classification, pct_human, and pct_mouse).

object

Which kind of object x is: "seurat" (the default) or "sce" for a SingleCellExperiment.

remove

Logical. If TRUE (the default), the detected multiplets are removed from the returned object. If FALSE, all cells are kept and only the metadata is added.

barcode_col

Name of the barcode column in multiplets. Default "barcode".

Details

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.

Value

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.

Examples

# 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")