scPAS identifies phenotype-associated cell subpopulations through a multi-step computational pipeline that integrates bulk and single-cell RNA-seq data.
scPAS Workflow Overview
Given:
The goal is to find gene weights \(\boldsymbol{\beta}\) that associate gene expression with phenotype, then apply these weights to single-cell data to compute per-cell risk scores.
scPAS uses the APML0 (Augmented and Penalized Minimization L0) algorithm with network regularization:
\[ \hat{\boldsymbol{\beta}} = \arg\min_{\boldsymbol{\beta}} \left\{ L(\boldsymbol{\beta}; \mathbf{X}, \mathbf{y}) + \lambda_1 \|\boldsymbol{\beta}\|_1 + \lambda_2 \boldsymbol{\beta}^T \mathbf{L} \boldsymbol{\beta} \right\} \]
Where:
Effect of Network Regularization
For continuous phenotypes, we minimize the squared error:
\[ L(\boldsymbol{\beta}) = \frac{1}{2n} \sum_{i=1}^{n} (y_i - \mathbf{x}_i^T \boldsymbol{\beta})^2 \]
For binary outcomes, we use logistic regression:
\[ L(\boldsymbol{\beta}) = -\frac{1}{n} \sum_{i=1}^{n} \left[ y_i \log(p_i) + (1-y_i) \log(1-p_i) \right] \]
where \(p_i = \frac{1}{1 + e^{-\mathbf{x}_i^T \boldsymbol{\beta}}}\)
For time-to-event data, we minimize the negative partial log-likelihood:
\[ L(\boldsymbol{\beta}) = -\frac{1}{n} \sum_{i: \delta_i = 1} \left[ \mathbf{x}_i^T \boldsymbol{\beta} - \log \sum_{j \in R(t_i)} e^{\mathbf{x}_j^T \boldsymbol{\beta}} \right] \]
where \(R(t_i)\) is the risk set at time \(t_i\) and \(\delta_i\) is the event indicator.
Once the model is trained, the risk score for each cell is computed as:
\[ RS_j = \sum_{g=1}^{p} \hat{\beta}_g \cdot \tilde{S}_{jg} \]
where:
Risk Score Distribution
The raw risk score is converted to a Z-statistic:
\[ NRS_j = \frac{RS_j - \mu_{bg}}{\sigma_{bg}} \]
where \(\mu_{bg}\) and \(\sigma_{bg}\) are the mean and standard deviation of the background distribution estimated from permutation.
To assess significance, scPAS performs a permutation test:
Permutation Test Principle
Algorithm:
\[ p_j = \frac{1}{B} \sum_{b=1}^{B} \mathbb{I}(|RS_j^{(b)}| \geq |RS_j|) \]
Multiple testing correction using Benjamini-Hochberg procedure:
\[ FDR_j = \min\left(1, \frac{p_j \cdot m}{\text{rank}(p_j)}\right) \]
where \(m\) is the total number of cells.
Cells are classified based on:
| Category | Criteria |
|---|---|
| scPAS+ | FDR < 0.05 AND NRS > 0 |
| scPAS- | FDR < 0.05 AND NRS < 0 |
| 0 | FDR ≥ 0.05 |
Cell Classification Scheme
scPAS uses efficient sparse matrix operations for large-scale single-cell data:
# Efficient correlation calculation for sparse matrices
sparse.cor <- function(x) {
# Uses optimized algorithm that avoids dense conversion
# Handles numerical precision issues
# Returns proper correlation matrix
}
# Efficient row scaling
sparse_row_scale <- function(x, center = TRUE, scale = TRUE) {
# Row-wise standardization
# Preserves sparsity when only scaling (not centering)
}Original scPAS Paper: Xie A, et al. (2024). scPAS: single-cell phenotype-associated subpopulation identifier. Briefings in Bioinformatics, 26(1):bbae655.
Network-Regularized Regression: Zou H, Hastie T. (2005). Regularization and variable selection via the elastic net. JRSS-B, 67(2):301-320.
Permutation Testing: Westfall PH, Young SS. (1993). Resampling-Based Multiple Testing. Wiley.
sessionInfo()
#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04 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.32.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] Matrix_1.7-5 ggplot2_4.0.3 rmarkdown_2.31
#>
#> loaded via a namespace (and not attached):
#> [1] vctrs_0.7.3 cli_3.6.6 knitr_1.51 rlang_1.3.0
#> [5] xfun_0.60 otel_0.2.0 generics_0.1.4 S7_0.2.2
#> [9] jsonlite_2.0.0 labeling_0.4.3 glue_1.8.1 buildtools_1.0.0
#> [13] htmltools_0.5.9 maketools_1.3.2 sys_3.4.3 sass_0.4.10
#> [17] scales_1.4.0 grid_4.6.1 tibble_3.3.1 evaluate_1.0.5
#> [21] jquerylib_0.1.4 fastmap_1.2.0 yaml_2.3.12 lifecycle_1.0.5
#> [25] compiler_4.6.1 dplyr_1.2.1 RColorBrewer_1.1-3 pkgconfig_2.0.3
#> [29] lattice_0.22-9 farver_2.1.2 digest_0.6.39 R6_2.6.1
#> [33] tidyselect_1.2.1 pillar_1.11.1 magrittr_2.0.5 bslib_0.11.0
#> [37] withr_3.0.3 tools_4.6.1 gtable_0.3.6 cachem_1.1.0