### Install DoubletFinder Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/QUICKSTART.md Install the DoubletFinder package from GitHub using remotes. Use force = TRUE to ensure the latest version is installed. ```r remotes::install_github('chris-mcginnis-ucsf/DoubletFinder', force = TRUE) ``` -------------------------------- ### Complete DoubletFinder Workflow Example Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/09-workflow.md This comprehensive R script demonstrates the full DoubletFinder workflow using Seurat and DoubletFinder libraries. It covers preprocessing, parameter optimization using pK sweeps, Poisson and homotypic doublet estimation, and downstream analysis filtering. ```r library(Seurat) library(DoubletFinder) # 1. PREPROCESSING seu <- CreateSeuratObject(your_counts) seu <- NormalizeData(seu) seu <- FindVariableFeatures(seu) seu <- ScaleData(seu) seu <- RunPCA(seu) # 2. PARAMETER OPTIMIZATION sweep.list <- paramSweep(seu, PCs = 1:20, num.cores = 4) sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) bcmvn <- find.pK(sweep.stats) optimal.pK <- bcmvn$pK[which.max(bcmvn$BCmetric)] # 3. POISSON ESTIMATE nExp_poi <- round(0.075 * nrow(seu@meta.data)) seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = optimal.pK, nExp = nExp_poi, sct = FALSE) # 4. HOMOTYPIC ADJUSTMENT (optional) seu <- FindClusters(seu, resolution = 0.5) annotations <- seu$seurat_clusters homotypic.prop <- modelHomotypic(annotations) nExp_poi.adj <- round(nExp_poi * (1 - homotypic.prop)) pANN.col <- paste("pANN", 0.25, optimal.pK, nExp_poi, sep="_") seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = optimal.pK, nExp = nExp_poi.adj, reuse.pANN = pANN.col, sct = FALSE) # 5. DOWNSTREAM ANALYSIS classification.col <- paste("DF.classifications_0.25", optimal.pK, nExp_poi.adj, sep="_") seu.filtered <- subset(seu, subset = get(classification.col) == "Singlet") # Continue with standard analysis... ``` -------------------------------- ### Load pbmc_small Dataset in R Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/08-internal-functions.md Loads the example pbmc_small Seurat object for use in DoubletFinder workflows. Ensure the SeuratObject package is installed. ```r data(pbmc_small) seu <- pbmc_small ``` -------------------------------- ### DoubletFinder Quick Start Analysis Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/INDEX.md This snippet outlines the three main steps for a quick doublet detection analysis using DoubletFinder: parameter sweep for pK selection, estimating expected doublets, and running the doubletFinder function. ```r library(DoubletFinder) # 1. Parameter sweep + pK selection sweep.list <- paramSweep(seu, PCs = 1:20) sweep.stats <- summarizeSweep(sweep.list) bcmvn <- find.pK(sweep.stats) optimal.pK <- bcmvn$pK[which.max(bcmvn$BCmetric)] # 2. Estimate expected doublets nExp_poi <- round(0.075 * ncol(seu)) # 3. Run doubletFinder seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = optimal.pK, nExp = nExp_poi) ``` -------------------------------- ### Two-Step DoubletFinder Workflow with Homotypic Adjustment Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/05-modelHomotypic.md This comprehensive example outlines a two-step DoubletFinder workflow. It includes parameter sweeping to find optimal pK, an initial run with a Poisson doublet estimate, followed by clustering and homotypic proportion calculation to adjust the `nExp` for a second, more refined `doubletFinder` run. ```r library(DoubletFinder) # Preprocess data seu <- CreateSeuratObject(your_counts) seu <- NormalizeData(seu) seu <- FindVariableFeatures(seu, selection.method = "vst", nfeatures = 2000) seu <- ScaleData(seu) seu <- RunPCA(seu) # Run parameter sweep to identify optimal pK sweep.list <- paramSweep(seu, PCs = 1:10, sct = FALSE) sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) bcmvn <- find.pK(sweep.stats) optimal.pK <- bcmvn$pK[which.max(bcmvn$BCmetric)] # First run: Use Poisson doublet estimate nExp_poi <- round(0.075 * nrow(seu@meta.data)) seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = optimal.pK, nExp = nExp_poi, sct = FALSE) # Cluster to get cell type annotations for homotypic adjustment seu <- FindNeighbors(seu, dims = 1:10) seu <- FindClusters(seu) # Second run: Adjust for homotypic doublets annotations <- seu$seurat_clusters homotypic.prop <- modelHomotypic(annotations) nExp_poi.adj <- round(nExp_poi * (1 - homotypic.prop)) seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = optimal.pK, nExp = nExp_poi.adj, reuse.pANN = paste("pANN", 0.25, optimal.pK, nExp_poi, sep="_"), sct = FALSE) # Results in seu@meta.data include both classifications: # DF.classifications_0.25_0.01_913 (before homotypic adjustment) # DF.classifications_0.25_0.01_645 (after homotypic adjustment) ``` -------------------------------- ### Adjusting nExp with Homotypic Doublet Proportion Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/01-doubletFinder.md This example demonstrates how to refine the expected doublet number (nExp) by accounting for the proportion of homotypic doublets. It first runs DoubletFinder with a Poisson estimate, then models homotypic doublet proportions based on cell type annotations, and finally reruns DoubletFinder with the adjusted nExp. ```r # First run with Poisson estimate seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = 0.01, nExp = nExp_poi, sct = FALSE) # Model homotypic doublet proportion from cell type annotations annotations <- seu$cell_type homotypic.prop <- modelHomotypic(annotations) # Adjust nExp by subtracting homotypic doublets nExp_poi.adj <- round(nExp_poi * (1 - homotypic.prop)) # Rerun with adjusted nExp, reusing previously computed pANN seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = 0.01, nExp = nExp_poi.adj, reuse.pANN = "pANN_0.25_0.01_913", sct = FALSE) ``` -------------------------------- ### Tracking Doublet Type Contributors Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/01-doubletFinder.md This example shows how to enable the tracking of cell types that contribute to doublets. By providing cell type annotations, DoubletFinder creates new metadata columns indicating the contribution of each cell type to the identified doublets. ```r # Run with cell type annotations to track contributing cell types annotations <- seu$cell_type seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = 0.01, nExp = nExp_poi, sct = FALSE, annotations = annotations) # New metadata columns are created for each cell type: # DF.doublet.contributors_0.25_0.01_913_TypeA # DF.doublet.contributors_0.25_0.01_913_TypeB # etc. ``` -------------------------------- ### DoubletFinder for Drop-Seq Data Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md Configures DoubletFinder for Drop-Seq data, suggesting a conservative starting doublet rate that can be adjusted based on data inspection. ```r # Drop-Seq typically has ~5-10% doublets (check your data) doublet_rate <- 0.05 # Start conservative nExp <- round(doublet_rate * ncol(seu)) seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = 0.01, nExp = nExp, sct = FALSE) ``` -------------------------------- ### Basic DoubletFinder Usage with Poisson Rate Estimation Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/01-doubletFinder.md This snippet shows the fundamental steps for running DoubletFinder. It includes data loading, preprocessing, estimating the expected doublet number using a Poisson distribution, and executing the DoubletFinder function. Access the results directly from the Seurat object's metadata. ```r library(DoubletFinder) library(Seurat) # Load and preprocess data seu <- CreateSeuratObject(your_counts) seu <- NormalizeData(seu) seu <- FindVariableFeatures(seu, selection.method = "vst", nfeatures = 2000) seu <- ScaleData(seu) seu <- RunPCA(seu) # Estimate expected doublet number assuming 7.5% doublet rate nExp_poi <- round(0.075 * nrow(seu@meta.data)) # Run DoubletFinder with pK = 0.01 (adjust based on your pK selection) seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = 0.01, nExp = nExp_poi, sct = FALSE) # Access results in metadata head(seu@meta.data) ``` -------------------------------- ### Basic pK Selection Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/04-find.pK.md This snippet shows the basic workflow for performing a parameter sweep and finding the optimal pK value using the BCmetric. Ensure the DoubletFinder library is loaded and your Seurat object is prepared. ```r library(DoubletFinder) data(pbmc_small) seu <- pbmc_small # Perform parameter sweep sweep.list <- paramSweep(seu, PCs = 1:10, sct = FALSE) # Summarize results sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) # Find optimal pK bcmvn <- find.pK(sweep.stats) # Identify pK with highest BCmetric optimal.pK <- bcmvn$pK[which.max(bcmvn$BCmetric)] print(paste("Optimal pK:", optimal.pK)) ``` -------------------------------- ### DoubletFinder Workflow: Parameter Optimization and Detection Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/README.md This R code demonstrates the typical workflow for using DoubletFinder. It includes parameter optimization using `paramSweep`, `summarizeSweep`, and `find.pK`, followed by doublet detection with `doubletFinder`. ```r # 1. Parameter optimization sweep.list <- paramSweep(seu, PCs = 1:20) sweep.stats <- summarizeSweep(sweep.list) bcmvn <- find.pK(sweep.stats) optimal.pK <- bcmvn$pK[which.max(bcmvn$BCmetric)] # 2. Detection nExp <- round(0.075 * ncol(seu)) seu <- doubletFinder(seu, PCs = 1:20, pK = optimal.pK, nExp = nExp) ``` -------------------------------- ### Run DoubletFinder (Varying Stringencies) Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/README.md Runs DoubletFinder with different classification stringencies (pN and pK). The first call uses the calculated nExp_poi, and the second uses an adjusted nExp_poi.adj, reusing the previous pANN calculation. ```R ## Run DoubletFinder with varying classification stringencies ---------------------------------------------------------------- seu_kidney <- doubletFinder(seu_kidney, PCs = 1:10, pN = 0.25, pK = 0.09, nExp = nExp_poi, reuse.pANN = NULL, sct = FALSE) seu_kidney <- doubletFinder(seu_kidney, PCs = 1:10, pN = 0.25, pK = 0.09, nExp = nExp_poi.adj, reuse.pANN = "pANN_0.25_0.09_913", sct = FALSE) ``` -------------------------------- ### DoubletFinder with SCTransform Preprocessing Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md Demonstrates how to run DoubletFinder when the input object has been preprocessed with SCTransform, ensuring the 'sct' parameter matches. ```r # Must match sct parameter to preprocessing method seu <- SCTransform(seu) seu <- RunPCA(seu) seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = optimal.pK, nExp = nExp, sct = TRUE) ``` -------------------------------- ### Parameter Sweep with Parallelization Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/02-paramSweep.md Runs the parameter sweep using multiple cores for faster computation, which is most beneficial for large datasets. Ensure 'num.cores' is set appropriately. ```r # Use multiple cores for faster computation # Note: parallelization is most beneficial for large datasets sweep.list <- paramSweep(seu, PCs = 1:10, sct = FALSE, num.cores = 4) sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) bcmvn <- find.pK(sweep.stats) ``` -------------------------------- ### Minimum Viable Doublet Detection Workflow Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/QUICKSTART.md A complete workflow for running DoubletFinder, from Seurat object creation and preprocessing to finding the optimal pK value and performing doublet detection. The results are stored in new metadata columns. ```r library(DoubletFinder) library(Seurat) # Preprocess (standard Seurat workflow) seu <- CreateSeuratObject(your_counts) seu <- NormalizeData(seu) seu <- FindVariableFeatures(seu) seu <- ScaleData(seu) seu <- RunPCA(seu) # 1. Find optimal pK (one-time optimization per dataset) sweep.list <- paramSweep(seu, PCs = 1:20) sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) bcmvn <- find.pK(sweep.stats) optimal.pK <- bcmvn$pK[which.max(bcmvn$BCmetric)] # 2. Run doublet detection nExp_poi <- round(0.075 * ncol(seu)) seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = optimal.pK, nExp = nExp_poi) # 3. Access results seu@meta.data # New columns: pANN_*, DF.classifications_* ``` -------------------------------- ### Adjusting pK for Specific Scenarios Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md Provides guidance on selecting a smaller pK value when dealing with multiple cell types of significantly different sizes to prevent large populations from dominating. ```r # May need smaller pK to avoid large population dominating optimal.pK <- 0.005 # Smaller neighborhood ``` -------------------------------- ### DoubletFinder for Large Datasets (> 100k cells) Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md Recommends using paramSweep on downsampled data to find an optimal pK, then running DoubletFinder on the full dataset with a subset of PCs. ```r # Use paramSweep for pK selection on downsampled data sweep.list <- paramSweep(seu, PCs = 1:20, num.cores = 8) # ~10k cells used # Then run doubletFinder on full dataset with subset of PCs seu <- doubletFinder(seu, PCs = 1:15, pN = 0.25, pK = optimal.pK, nExp = nExp) ``` -------------------------------- ### Speed Optimization with Fewer Cores Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md For faster processing, especially on systems where core overhead is significant, reduce the number of cores used in `paramSweep`. This snippet demonstrates using fewer cores for parameter sweeping. ```r # Use fewer cores when overhead exceeds benefit sweep.list <- paramSweep(seu, PCs = 1:20, num.cores = 4) # Sweet spot for most systems ``` -------------------------------- ### Create and Preprocess Seurat Object Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/06-types.md This snippet shows the essential preprocessing steps required for a Seurat object before it can be used with DoubletFinder functions. Ensure all these steps are completed. ```r seu <- CreateSeuratObject(counts) seu <- NormalizeData(seu) seu <- FindVariableFeatures(seu) seu <- ScaleData(seu) seu <- RunPCA(seu) ``` -------------------------------- ### Pre-process Seurat Object (Standard) Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/README.md Standard pre-processing steps for a Seurat object, including normalization, feature selection, scaling, PCA, and UMAP. ```R ## Pre-process Seurat object (standard) -------------------------------------------------------------------------------------- seu_kidney <- CreateSeuratObject(kidney.data) seu_kidney <- NormalizeData(seu_kidney) seu_kidney <- FindVariableFeatures(seu_kidney, selection.method = "vst", nfeatures = 2000) seu_kidney <- ScaleData(seu_kidney) seu_kidney <- RunPCA(seu_kidney) seu_kidney <- RunUMAP(seu_kidney, dims = 1:10) ``` -------------------------------- ### Basic Parameter Sweep Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/02-paramSweep.md Performs a parameter sweep using default settings. This is useful for initial exploration of parameter space. ```r library(DoubletFinder) data(pbmc_small) seu <- pbmc_small # Perform parameter sweep with default settings sweep.list <- paramSweep(seu, PCs = 1:10, sct = FALSE) # Summarize results sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) # Find optimal pK bcmvn <- find.pK(sweep.stats) ``` -------------------------------- ### Run ParamSweep with pbmc_small in R Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/08-internal-functions.md Executes the paramSweep function on the loaded pbmc_small Seurat object to generate a parameter sweep list. This requires the Seurat object to have RunPCA called prior to use. ```r sweep.list <- paramSweep(seu, PCs = 1:10) ``` -------------------------------- ### Standard DoubletFinder Parameters Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md Use these standard parameters for most datasets. Adjust pK if needed based on your data's characteristics. ```r # Standard parameters pN <- 0.25 # Poisson estimate of doublets pK <- 0.01 # Medium neighborhood (start here; optimize if needed) nExp <- round(0.075 * ncol(seu)) # 7.5% doublet rate (adjust per platform) sct <- FALSE # Standard preprocessing seu <- doubletFinder(seu, PCs = 1:20, pN = pN, pK = pK, nExp = nExp, sct = sct) ``` -------------------------------- ### Select Optimal pK using Bimodality Coefficient Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/03-summarizeSweep.md This snippet shows how to select the optimal pK value after summarizing sweep results. It identifies the pK with the maximum Bimodality Coefficient (BCmetric) from the summarized statistics. ```r # After summarization, identify the pK with maximum BCreal sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) # Find pK values grouped by mean BC bc.mvn <- find.pK(sweep.stats) # The pK with highest BCmetric is typically optimal optimal.pK <- bc.mvn$pK[which.max(bc.mvn$BCmetric)] ``` -------------------------------- ### Parameter Sweep for pK Optimization Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/09-workflow.md Runs a parameter sweep to test various pN and pK values for doublet detection. It automatically downsamples large datasets and can be parallelized for speed. ```r # Run parameter sweep # Automatically tests pN = 0.05-0.30 and pK = 0.0005-0.30 sweep.list <- paramSweep(seu, PCs = 1:20, sct = FALSE, num.cores = 4) ``` -------------------------------- ### pK Identification (No Ground-Truth) Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/README.md Identifies the optimal pK value for doublet detection using the paramSweep and summarizeSweep functions when ground-truth labels are not available. ```R ## pK Identification (no ground-truth) --------------------------------------------------------------------------------------- sweep.res.list_kidney <- paramSweep(seu_kidney, PCs = 1:10, sct = FALSE) sweep.stats_kidney <- summarizeSweep(sweep.res.list_kidney, GT = FALSE) bcmvn_kidney <- find.pK(sweep.stats_kidney) ``` -------------------------------- ### paramSweep Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/INDEX.md Performs a parameter sweep to test multiple pN and pK combinations for doublet prediction. It generates pANN vectors for each combination and supports parallel processing. ```APIDOC ## paramSweep ### Description Tests multiple pN and pK parameter combinations for doublet prediction and generates pANN vectors for each combination. Supports parallelization. ### Method Not applicable (R function) ### Endpoint Not applicable (R function) ### Parameters #### Input - **Seurat object**: Preprocessed Seurat object. - **pN**: Vector of pN values to test. - **pK**: Vector of pK values to test. - **num.cores**: Number of CPU cores to use for parallelization. #### Output - **List**: A list containing pANN vectors for each pN-pK combination. ``` -------------------------------- ### paramSweep Function Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/QUICKSTART.md Calculates pANN values for a range of pN and pK parameters. Use sct = TRUE if using Seurat's SCTransform normalization. Specify num.cores for parallel processing. ```r paramSweep(seu, PCs = 1:20, sct = FALSE, num.cores = 4) # Returns: List of pANN vectors for all pN-pK combinations ``` -------------------------------- ### Speed Optimization with Fewer PCs Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md If computational resources are limited, consider using fewer principal components (PCs) when running DoubletFinder. This can reduce computation time. ```r # Use fewer PCs if computationally limited seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = optimal.pK, nExp = nExp) ``` -------------------------------- ### Adjust Doublet Expectations for Realistic Detection Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/05-modelHomotypic.md This snippet demonstrates a multi-step process to refine doublet detection by first estimating total doublets using a Poisson model, then calculating the homotypic doublet proportion, and finally adjusting the expected doublet count (`nExp`) to account for undetectable homotypic doublets before running `doubletFinder`. ```r library(DoubletFinder) data(pbmc_small) seu <- pbmc_small # Step 1: Estimate total doublets assuming 7.5% doublet rate total_cells <- nrow(seu@meta.data) nExp_poi <- round(0.075 * total_cells) print(paste("Poisson estimate of total doublets:", nExp_poi)) # Step 2: Model homotypic doublet proportion annotations <- seu$RNA_snn_res.1 homotypic.prop <- modelHomotypic(annotations) print(paste("Estimated homotypic proportion:", homotypic.prop)) # Step 3: Adjust nExp to account for undetectable homotypic doublets nExp_poi.adj <- round(nExp_poi * (1 - homotypic.prop)) print(paste("Adjusted doublet expectation:", nExp_poi.adj)) # Step 4: Run DoubletFinder with adjusted nExp seu <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = 0.01, nExp = nExp_poi.adj, sct = FALSE) # Verify results doublet.counts <- table(seu$DF.classifications_0.25_0.01) print(doublet.counts) ``` -------------------------------- ### DoubletFinder Key Settings Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/QUICKSTART.md Defines the standard and optimizable parameters for DoubletFinder. Adjust `pK` and `nExp` based on your dataset and platform's expected doublet rate. ```r # Platform doublet rates (adjust nExp accordingly) 10X Genomics ← 7.5% (most common) Drop-Seq ← 5–10% Parse ← ~5% # Standard parameters (rarely change) pN = 0.25 ← Poisson estimate of artificial doublets PCs = 1:20 ← Use elbow plot to determine range # Parameters YOU must optimize pK = ??? ← Use paramSweep to find (typically 0.005–0.05) nExp = ??? ← Calculate from doublet rate × ncells ``` -------------------------------- ### Pre-process Seurat Object (SCTransform) Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/README.md Pre-processing using the SCTransform method for a Seurat object, followed by PCA and UMAP. ```R ## Pre-process Seurat object (sctransform) ----------------------------------------------------------------------------------- seu_kidney <- CreateSeuratObject(kidney.data) seu_kidney <- SCTransform(seu_kidney) seu_kidney <- RunPCA(seu_kidney) seu_kidney <- RunUMAP(seu_kidney, dims = 1:10) ``` -------------------------------- ### Summarize Parameter Sweep without Ground-Truth Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/03-summarizeSweep.md Use this snippet to summarize parameter sweep results and identify optimal pK based on the Bimodality Coefficient (BCreal) when ground-truth classifications are not available. It requires the DoubletFinder library and a Seurat object. ```r library(DoubletFinder) data(pbmc_small) seu <- pbmc_small # Perform parameter sweep sweep.list <- paramSweep(seu, PCs = 1:10, sct = FALSE) # Summarize without ground-truth sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) # View results head(sweep.stats) # pN pK BCreal # 1 0.05 0.0005 0.5234 # 2 0.05 0.001 0.6122 # ... # Find optimal pK from BCreal values bcmvn <- find.pK(sweep.stats) ``` -------------------------------- ### pK Selection DataFrame Structure Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/06-types.md Illustrates the structure of the DataFrame returned by find.pK, used for selecting the optimal pK value. It contains metrics like mean bimodality coefficient and its variance. ```r bc.mvn <- data.frame( ParamID = integer, # Sequential ID pK = numeric, # pK value MeanBC = numeric, # Mean bimodality coefficient VarBC = numeric, # Variance of bimodality coefficient BCmetric = numeric, # Mean-variance normalized BC MeanAUC = numeric # (Optional) Mean AUC if ground-truth used ) ``` -------------------------------- ### DoubletFinder with Homotypic Adjustment Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/QUICKSTART.md Run DoubletFinder in three steps: initial detection, adjusting nExp for homotypic doublets using cell type annotations, and rerunning with the adjusted nExp. This method is recommended for more accurate results. ```r # Step 1: Initial detection seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = 0.01, nExp = nExp_poi) # Step 2: Adjust nExp for homotypic doublets annotations <- seu$seurat_clusters # Or your cell type annotations homotypic.prop <- modelHomotypic(annotations) nExp_poi.adj <- round(nExp_poi * (1 - homotypic.prop)) # Step 3: Rerun with adjusted nExp (fast—reuses pANN) pANN.col <- paste("pANN_0.25_0.01", nExp_poi, sep="_") seu <- doubletFinder(seu, PCs = 1:20, pN = 0.25, pK = 0.01, nExp = nExp_poi.adj, reuse.pANN = pANN.col) ``` -------------------------------- ### SCTransform Preprocessing Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/09-workflow.md Applies SCTransform for normalization and scaling in a single step, followed by PCA. This is an alternative to the standard preprocessing pipeline. ```r # SCTransform-based preprocessing (normalizes and scales in one step) seu <- SCTransform(seu, verbose = FALSE) seu <- RunPCA(seu) ``` -------------------------------- ### Pre-flight Checks for DoubletFinder Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/07-errors.md Verify Seurat object preprocessing, ensure nExp is reasonable, and validate annotations before running DoubletFinder. These checks help prevent errors and ensure correct input. ```r # 1. Verify Seurat object is preprocessed stopifnot("pca" %in% names(seu@reductions)) stopifnot(length(seu@commands) > 0) # 2. Verify nExp is reasonable nExp_poi <- round(0.075 * ncol(seu)) stopifnot(nExp_poi < ncol(seu)) stopifnot(nExp_poi > 0) # 3. If providing annotations, verify they're valid if (!is.null(annotations)) { stopifnot(is.character(annotations)) stopifnot(length(annotations) == ncol(seu)) stopifnot(!any(is.na(annotations))) } ``` -------------------------------- ### paramSweep Function Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/MANIFEST.txt Performs a parameter sweep to find the optimal pK value for DoubletFinder by evaluating doublet detection across a range of pK values. ```APIDOC ## paramSweep_doubletFinder ### Description Automates the process of finding an optimal pK value for DoubletFinder by systematically evaluating doublet detection across a range of pK values. This function helps in determining the most appropriate pK for downstream analysis. ### Method Function Call (R) ### Parameters #### Required Parameters - **seurat_obj** (Seurat Object) - The input Seurat object. - **PCs** (numeric vector) - Principal components to use for the analysis. - **max.้pK** (numeric) - The maximum pK value to consider in the sweep. The sweep will range from 0 to this value. - **num.cores** (numeric) - The number of CPU cores to use for parallel processing. #### Optional Parameters - ** eğitim.pANN** (logical) - If TRUE, calculates and stores the pANN values for each cell. Defaults to TRUE. - **reuse.pANN** (logical) - If TRUE, uses pre-computed pANN values from the Seurat object. Defaults to FALSE. - **dims** (numeric vector) - Alias for PCs. If provided, overrides PCs. ### Return Value A list containing the results of the parameter sweep, including pK values, expected doublet counts, and doublet scores. ### Example ```R # Assuming 'seurat_obj' is a Seurat object # Perform parameter sweep for pK values up to 1.5 using 4 cores param_sweep_results <- paramSweep_doubletFinder(seurat_obj, PCs = 1:10, max.้pK = 1.5, num.cores = 4) # Summarize the sweep results to help choose an optimal pK summary_results <- summarizeSweep(param_sweep_results) print(summary_results) ``` ``` -------------------------------- ### Create Gaussian Kernel Density Estimate Function Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/06-types.md Generates a function for Gaussian kernel density estimation using the KernSmooth package. This function takes a numeric vector (e.g., pANN) and returns the estimated probability density at query points. ```r # Gaussian kernel density estimate gkde <- approxfun(bkde(pANN_vector, kernel = "normal")) ``` -------------------------------- ### Accessing Specific pN-pK Results Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/02-paramSweep.md Demonstrates how to access the pANN values for a specific parameter combination (pN and pK) and a particular cell barcode from the results of a parameter sweep. ```r sweep.list <- paramSweep(seu, PCs = 1:10) # Access pANN values for specific parameter combination pann_pN0.25_pK0.01 <- sweep.list$pN_0.25_pK_0.01 # Get pANN values for a specific cell cell_pann <- pann_pN0.25_pK0.01["your_cell_barcode", "pANN"] ``` -------------------------------- ### Selecting pK with Multiple Peaks Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/04-find.pK.md When the find.pK function identifies multiple peaks in the BCmetric, this snippet demonstrates how to examine the top candidates and manually spot-check them using DoubletFinder. This approach helps in visually validating the best pK for your data. ```r # Find parameter sweep results sweep.list <- paramSweep(seu, PCs = 1:10) sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) bcmvn <- find.pK(sweep.stats) # When multiple peaks exist, examine top 3 candidates top_pK_indices <- order(bcmvn$BCmetric, decreasing = TRUE)[1:3] candidate_pK_values <- bcmvn$pK[top_pK_indices] print(candidate_pK_values) # [1] 0.01 0.02 0.015 # Manually spot-check in UMAP/tSNE space: # Run doubletFinder with each pK and visually compare results for (pk in candidate_pK_values) { seu.test <- doubletFinder(seu, PCs = 1:10, pN = 0.25, pK = pk, nExp = round(0.15 * nrow(seu@meta.data))) # Visualize seu.test and evaluate which doublet pattern makes sense } ``` -------------------------------- ### Standard Seurat Preprocessing Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/09-workflow.md Performs standard Seurat preprocessing steps including normalization, feature selection, scaling, and PCA. This is a prerequisite for DoubletFinder analysis. ```r library(Seurat) library(DoubletFinder) # Create Seurat object from count matrix seu <- CreateSeuratObject(counts = your_expression_matrix, project = "project_name", min.cells = 3, min.features = 200) # Remove low-quality cells (optional but recommended) seu[["percent.mt"]] <- PercentageFeatureSet(seu, pattern = "^MT-") seu <- subset(seu, subset = nFeature_RNA > 200 & nFeature_RNA < 2500 & percent.mt < 5) # Standard preprocessing pipeline seu <- NormalizeData(seu) seu <- FindVariableFeatures(seu, selection.method = "vst", nfeatures = 2000) seu <- ScaleData(seu) seu <- RunPCA(seu) # Visualize PC contributions ElbowPlot(seu, ndims = 50) # Determine number of significant PCs (e.g., 1:20 based on elbow plot) ``` -------------------------------- ### summarizeSweep Function Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/QUICKSTART.md Summarizes the output from paramSweep by calculating bimodality coefficients for each pN-pK combination. ```r summarizeSweep(sweep.list, GT = FALSE) # Returns: Data frame with bimodality coefficients ``` -------------------------------- ### Parameter Sweep with SCTransform Preprocessing Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/02-paramSweep.md Executes the parameter sweep after preprocessing the Seurat object with SCTransform. Set 'sct = TRUE' to match the preprocessing method. ```r # Preprocess with SCTransform first seu <- CreateSeuratObject(your_counts) seu <- SCTransform(seu) seu <- RunPCA(seu) # Run sweep with sct = TRUE to match preprocessing sweep.list <- paramSweep(seu, PCs = 1:15, sct = TRUE, num.cores = 4) sweep.stats <- summarizeSweep(sweep.list, GT = FALSE) bcmvn <- find.pK(sweep.stats) ``` -------------------------------- ### Access Seurat Object Counts by Version Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/06-types.md This code demonstrates how to access the count matrix from a Seurat object, adapting to differences between Seurat v5 and earlier versions (v3-4). Use this to retrieve the raw counts for downstream analysis. ```r if (SeuratObject::Version(seu) >= '5.0') { # Seurat v5: Use LayerData() to access counts counts <- LayerData(seu, assay = "RNA", layer = "counts") } else { # Seurat v3-4: Use GetAssayData() counts <- GetAssayData(seu, assay = "RNA", slot = "counts") } ``` -------------------------------- ### summarizeSweep Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/INDEX.md Summarizes the results of a parameter sweep by computing the bimodality coefficient for each pN-pK combination. It can optionally perform ROC analysis. ```APIDOC ## summarizeSweep ### Description Summarizes parameter sweep results by computing the bimodality coefficient for each pN-pK combination. Supports optional ROC analysis. ### Method Not applicable (R function) ### Endpoint Not applicable (R function) ### Parameters #### Input - **Sweep results**: Output from `paramSweep`. - **ground.truth**: Optional vector of ground-truth labels (singlet/doublet). #### Output - **Data frame**: Summary of sweep results including bimodality coefficients. ``` -------------------------------- ### Automatic pK Filtering Logic in paramSweep Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/10-configuration.md This R code demonstrates the internal logic used by paramSweep to filter pK values. It ensures that each pK value tested results in at least one cell being identified within its neighborhood. ```r # Internal logic in paramSweep min.cells <- round(nrow(seu@meta.data)/(1-0.05) - nrow(seu@meta.data)) pK.test <- round(pK * min.cells) pK <- pK[which(pK.test >= 1)] ``` -------------------------------- ### Handle Seurat Version Differences for Counts Layer Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/07-errors.md Retrieves counts data, adapting to Seurat object versions 5.0 and above versus older versions. Requires Seurat version 3.0 or higher. ```r if (SeuratObject::Version(seu) >= '5.0') { counts <- LayerData(seu, assay = "RNA", layer = "counts") } else { counts <- GetAssayData(seu, assay = "RNA", slot = "counts") } ``` -------------------------------- ### Summarize Parameter Sweep with Ground-Truth for ROC Analysis Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/03-summarizeSweep.md This snippet demonstrates how to summarize parameter sweep results using ground-truth doublet classifications for ROC analysis. It calculates AUC and BCreal, enabling selection of optimal pK based on both metrics. Ensure ground-truth classifications are correctly formatted. ```r # Assuming ground-truth doublet classifications are stored in metadata data(pbmc_small) seu <- pbmc_small # Create example ground-truth vector gt.calls <- c(rep("Singlet", 75), rep("Doublet", 5)) # Perform parameter sweep sweep.list <- paramSweep(seu, PCs = 1:10, sct = FALSE) # Summarize with ground-truth for ROC analysis sweep.stats <- summarizeSweep(sweep.list, GT = TRUE, GT.calls = gt.calls) # View results including AUC head(sweep.stats) # pN pK AUC BCreal # 1 0.05 0.0005 0.8234 0.5234 # 2 0.05 0.001 0.8912 0.6122 # ... # Plot with find.pK shows both AUC (black line) and BCmetric (blue line) bcmvn <- find.pK(sweep.stats) ``` -------------------------------- ### find.pK Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/INDEX.md Identifies the optimal pK value for doublet detection by computing the mean-variance normalized bimodality coefficient (BCmvn) and visualizing the results. ```APIDOC ## find.pK ### Description Identifies the optimal pK value by computing the mean-variance normalized bimodality coefficient (BCmvn) and visualizing results. ### Method Not applicable (R function) ### Endpoint Not applicable (R function) ### Parameters #### Input - **Sweep results**: Output from `paramSweep`. - **ground.truth**: Optional vector of ground-truth labels. #### Output - **Numeric**: The identified optimal pK value. ``` -------------------------------- ### Internal Parallelization for Parameter Sweep Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/08-internal-functions.md This function is an internal helper for parameter sweeping, designed to be called by `paramSweep`. It processes one pN value across all pK values in parallel or serial execution. ```r parallel_paramSweep(n, n.real.cells, real.cells, pK, pN, data, orig.commands, PCs, sct) ``` -------------------------------- ### Compare Homotypic Proportions with Different Annotation Granularities Source: https://github.com/chris-mcginnis-ucsf/doubletfinder/blob/master/_autodocs/05-modelHomotypic.md Illustrates how the granularity of cell type annotations can affect the calculated homotypic doublet proportion. Finer-grained annotations typically result in lower homotypic proportions compared to coarser annotations. ```r # Fine-grained annotations (more cell types) annotations_fine <- seu$fine_cell_types # e.g., "Naive T cell", "Memory T cell" # Coarse annotations (fewer cell types) annotations_coarse <- seu$coarse_cell_types # e.g., "T cell" # Calculate proportions homotypic.prop.fine <- modelHomotypic(annotations_fine) homotypic.prop.coarse <- modelHomotypic(annotations_coarse) print(paste("Homotypic proportion (fine):", homotypic.prop.fine)) print(paste("Homotypic proportion (coarse):", homotypic.prop.coarse)) # Fine-grained annotations typically yield lower homotypic proportions # because "Naive T cell" and "Memory T cell" are distinct transcriptionally ```