Quick Start Guide

Introduction

scPharm is a computational framework for identifying pharmacological subpopulations of single cells in cancer research. By integrating single-cell RNA sequencing (scRNA-seq) data with pharmacogenomics profiles from the GDSC2 database, scPharm enables:

  • Classification of cells into drug-sensitive and drug-resistant subpopulations
  • Prioritization of therapeutic agents based on tumor cell sensitivity
  • Prediction of drug side effects on non-malignant cells
  • Identification of synergistic drug combinations

This vignette provides a quick introduction to get you started with scPharm.

Installation

# From R-universe (recommended)
install.packages("scPharm", repos = "https://zaoqu-liu.r-universe.dev")

# From GitHub
remotes::install_github("Zaoqu-Liu/scPharm")

Load Required Packages

library(scPharm)
library(Seurat)
library(ggplot2)

Prepare Example Data

For demonstration, we’ll create a simulated Seurat object with genes matching the GDSC2 database.

# Load reference gene annotations
data(bulkdata, package = "scPharm")
data(copykat_full.anno.hg20, package = "scPharm")

# Get real gene names
real_genes <- intersect(rownames(bulkdata), copykat_full.anno.hg20$hgnc_symbol)

# Create simulated data
set.seed(42)
genes <- sample(real_genes, 3000)
n_cells <- 200

# Simulate count matrix
counts <- matrix(rpois(length(genes) * n_cells, lambda = 10), 
                 nrow = length(genes), ncol = n_cells)
rownames(counts) <- genes
colnames(counts) <- paste0("Cell_", seq_len(n_cells))

# Add variation
high_var_genes <- sample(length(genes), 300)
counts[high_var_genes, ] <- counts[high_var_genes, ] + 
  rpois(300 * n_cells, lambda = 25)

# Create Seurat object
seurat_obj <- CreateSeuratObject(counts = counts, 
                                  min.cells = 3, 
                                  min.features = 200)
seurat_obj <- NormalizeData(seurat_obj, verbose = FALSE)

print(seurat_obj)
#> An object of class Seurat 
#> 3000 features across 200 samples within 1 assay 
#> Active assay: RNA (3000 features, 0 variable features)
#>  2 layers present: counts, data

Basic Workflow

Step 1: Identify Pharmacological Subpopulations

The core function scPharmIdentify() classifies cells based on their drug response profiles.

# For cell line data (no CNV detection needed)
result <- scPharmIdentify(
  seurat_obj,
  type = "cellline",      # or "tissue" for patient samples

  cancer = "BRCA",        # TCGA cancer type
  drug = "Docetaxel",     # Drug name or "all"
  nmcs = 30,              # Number of MCA components
  nfeatures = 150,        # Features for cell signatures
  cores = 4               # Parallel cores
)

For tissue samples with tumor/normal cell mixtures:

# Automatic tumor detection via CNV analysis
result <- scPharmIdentify(
  seurat_obj,
  type = "tissue",
  cancer = "LUAD"
)

# Or provide known tumor cell barcodes
tumor_cells <- c("Cell_1", "Cell_2", "Cell_3", ...)
result <- scPharmIdentify(
  seurat_obj,
  type = "tissue",
  cancer = "LUAD",
  tumor.cells = tumor_cells
)

Step 2: Drug Prioritization

Rank drugs by their effectiveness on tumor cells:

# Compute drug prioritization scores
dr_scores <- scPharmDr(result)

# View top drugs
head(dr_scores)

Step 3: Predict Drug Side Effects

For tissue samples, estimate potential toxicity on non-malignant cells:

# Compute drug side effect scores
dse_scores <- scPharmDse(result)

# View results
head(dse_scores)

Step 4: Identify Drug Combinations

Find synergistic drug pairs targeting complementary resistant populations:

# Identify combinations for top 5 drugs
combos <- scPharmCombo(result, dr_scores, topN = 5)

# View combination results
names(combos)

Understanding Output

Cell Labels

After running scPharmIdentify(), the Seurat object contains new metadata columns:

Column Description
cell.label Cell type: “tumor” or “adjacent”
scPharm_label_<drug> Drug response: “sensitive”, “resistant”, or “other”
scPharm_nes_<drug> Normalized Enrichment Score (NES)
# Check metadata
head(result@meta.data)

# Count cell labels
table(result@meta.data$cell.label)
table(result@meta.data$`scPharm_label_Docetaxel`)

Drug Prioritization Score (Dr)

The Dr score integrates:

  • Proportion of sensitive cells
  • Mean NES of sensitive cells
  • Distribution of response across the tumor

Lower Dr = Better drug candidate

Drug Side Effect Score (Dse)

The Dse score measures potential toxicity:

  • Based on NES distribution in adjacent (non-tumor) cells
  • Higher Dse = More potential side effects

Parameter Guidelines

Parameter Recommended Range Notes
nmcs 30-50 Higher for complex datasets
nfeatures 100-200 Balance between specificity and coverage
threshold.s Default or from scPharmGenNullDist() Sensitive threshold
threshold.r Default or from scPharmGenNullDist() Resistant threshold
cores 1-8 Parallel processing

Supported Cancer Types

scPharm supports all major TCGA cancer types:

#> BRCA, LUAD, LUSC, COAD, STAD, LIHC, KIRC, OV, PAAD, GBM, SKCM, HNSC, BLCA, PRAD, UCEC, ESCA, THCA, pan

Use cancer = "pan" for pan-cancer analysis.

Next Steps

Session Info

sessionInfo()
#> R version 4.5.3 (2026-03-11)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#> 
#> Matrix products: default
#> BLAS:   /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3 
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so;  LAPACK version 3.12.0
#> 
#> locale:
#>  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
#>  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
#>  [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
#>  [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
#>  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       
#> 
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#> 
#> attached base packages:
#> [1] stats     graphics  grDevices utils     datasets  methods   base     
#> 
#> other attached packages:
#> [1] scPharm_1.0.6      Seurat_5.5.0       SeuratObject_5.4.0 sp_2.2-1          
#> [5] dplyr_1.2.1        ggplot2_4.0.3      rmarkdown_2.31    
#> 
#> loaded via a namespace (and not attached):
#>   [1] RcppAnnoy_0.0.23            splines_4.5.3              
#>   [3] later_1.4.8                 tibble_3.3.1               
#>   [5] polyclip_1.10-7             fastDummies_1.7.6          
#>   [7] lifecycle_1.0.5             globals_0.19.1             
#>   [9] lattice_0.22-9              MASS_7.3-65                
#>  [11] magrittr_2.0.5              plotly_4.12.0              
#>  [13] sass_0.4.10                 jquerylib_0.1.4            
#>  [15] yaml_2.3.12                 httpuv_1.6.17              
#>  [17] otel_0.2.0                  sctransform_0.4.3          
#>  [19] spam_2.11-3                 askpass_1.2.1              
#>  [21] spatstat.sparse_3.1-0       reticulate_1.46.0          
#>  [23] cowplot_1.2.0               pbapply_1.7-4              
#>  [25] buildtools_1.0.0            RColorBrewer_1.1-3         
#>  [27] abind_1.4-8                 Rtsne_0.17                 
#>  [29] GenomicRanges_1.63.2        purrr_1.2.2                
#>  [31] mixtools_2.0.0.1            BiocGenerics_0.57.1        
#>  [33] IRanges_2.45.0              S4Vectors_0.49.2           
#>  [35] ggrepel_0.9.8               irlba_2.3.7                
#>  [37] listenv_0.10.1              spatstat.utils_3.2-2       
#>  [39] maketools_1.3.2             umap_0.2.10.0              
#>  [41] goftest_1.2-3               RSpectra_0.16-2            
#>  [43] spatstat.random_3.4-5       fitdistrplus_1.2-6         
#>  [45] parallelly_1.47.0           codetools_0.2-20           
#>  [47] DelayedArray_0.37.1         scuttle_1.21.6             
#>  [49] tidyselect_1.2.1            farver_2.1.2               
#>  [51] ScaledMatrix_1.19.0         viridis_0.6.5              
#>  [53] matrixStats_1.5.0           stats4_4.5.3               
#>  [55] spatstat.explore_3.8-0      Seqinfo_1.1.0              
#>  [57] jsonlite_2.0.0              BiocNeighbors_2.5.4        
#>  [59] progressr_0.19.0            ggridges_0.5.7             
#>  [61] survival_3.8-6              scater_1.39.4              
#>  [63] tictoc_1.2.1                segmented_2.2-1            
#>  [65] tools_4.5.3                 ica_1.0-3                  
#>  [67] Rcpp_1.1.1-1                glue_1.8.1                 
#>  [69] gridExtra_2.3               SparseArray_1.11.13        
#>  [71] xfun_0.57                   MatrixGenerics_1.23.0      
#>  [73] withr_3.0.2                 fastmap_1.2.0              
#>  [75] openssl_2.4.0               digest_0.6.39              
#>  [77] rsvd_1.0.5                  R6_2.6.1                   
#>  [79] mime_0.13                   scattermore_1.2            
#>  [81] tensor_1.5.1                spatstat.data_3.1-9        
#>  [83] tidyr_1.3.2                 generics_0.1.4             
#>  [85] data.table_1.18.2.1         httr_1.4.8                 
#>  [87] htmlwidgets_1.6.4           S4Arrays_1.11.1            
#>  [89] uwot_0.2.4                  pkgconfig_2.0.3            
#>  [91] gtable_0.3.6                lmtest_0.9-40              
#>  [93] S7_0.2.2                    SingleCellExperiment_1.33.2
#>  [95] XVector_0.51.0              sys_3.4.3                  
#>  [97] htmltools_0.5.9             dotCall64_1.2              
#>  [99] fgsea_1.37.4                scales_1.4.0               
#> [101] Biobase_2.71.0              png_0.1-9                  
#> [103] spatstat.univar_3.1-7       knitr_1.51                 
#> [105] reshape2_1.4.5              nlme_3.1-169               
#> [107] cachem_1.1.0                zoo_1.8-15                 
#> [109] stringr_1.6.0               KernSmooth_2.23-26         
#> [111] parallel_4.5.3              miniUI_0.1.2               
#> [113] vipor_0.4.7                 pillar_1.11.1              
#> [115] grid_4.5.3                  vctrs_0.7.3                
#> [117] RANN_2.6.2                  promises_1.5.0             
#> [119] BiocSingular_1.27.1         beachmat_2.27.5            
#> [121] xtable_1.8-8                cluster_2.1.8.2            
#> [123] beeswarm_0.4.0              CelliD_1.19.1              
#> [125] evaluate_1.0.5              cli_3.6.6                  
#> [127] compiler_4.5.3              rlang_1.2.0                
#> [129] future.apply_1.20.2         labeling_0.4.3             
#> [131] RcppArmadillo_15.2.6-1      plyr_1.8.9                 
#> [133] ggbeeswarm_0.7.3            stringi_1.8.7              
#> [135] viridisLite_0.4.3           deldir_2.0-4               
#> [137] BiocParallel_1.45.0         lazyeval_0.2.3             
#> [139] spatstat.geom_3.7-3         Matrix_1.7-5               
#> [141] RcppHNSW_0.6.0              patchwork_1.3.2            
#> [143] sparseMatrixStats_1.23.0    future_1.70.0              
#> [145] shiny_1.13.0                SummarizedExperiment_1.41.1
#> [147] kernlab_0.9-33              ROCR_1.0-12                
#> [149] igraph_2.3.0                bslib_0.10.0               
#> [151] fastmatch_1.1-8