scCS.single¶
single.py — SingleScorer: single-condition commitment score analysis for scCS.
Orchestrates: 1. RNA velocity computation (optional, via scVelo) 2. Radial star embedding construction (embedding.py) 3. FateMap construction from user-supplied cluster labels (bifurcation.py) 4. Commitment score computation (scores.py) 5. Driver gene analysis (drivers.py) 6. Pathway enrichment (enrichment.py) 7. Plotting (plot.py)
Quick start¶
>>> import scCS
>>> scorer = scCS.SingleScorer(
... adata,
... root='17',
... branches=['Monocyte', 'DC', 'Neutrophil'],
... obs_key='leiden',
... )
>>> scorer.build_embedding(ordering_metric='pseudotime')
>>> scorer.fit()
>>> result = scorer.score()
>>> print(result.summary())
>>> scorer.plot_star(result)
>>> # Driver genes
>>> vel_drivers = scorer.get_velocity_drivers()
>>> deg_drivers = scorer.get_deg_drivers()
>>> # Pathway enrichment (mouse)
>>> enrichment = scorer.get_enrichment(deg_drivers)
Classes¶
RNA velocity commitment scorer with radial star embedding. |
Module Contents¶
- class scCS.single.SingleScorer(adata, root: str, branches: List[str], obs_key: str = 'leiden', n_angle_bins: int = 36, sector_method: scCS._base.SectorMode = 'centroid', copy: bool = False)[source]¶
Bases:
scCS._base._BaseScorerRNA velocity commitment scorer with radial star embedding.
Computes commitment scores for a k-furcation defined by a single user-supplied bifurcation cluster and k terminal fate clusters.
The embedding places the bifurcation cluster at the origin and arranges each fate on its own radial arm, with cells ordered by differentiation level (pseudotime, CytoTRACE2, or custom score).
- Parameters:
adata (AnnData) – Single-cell dataset.
root (str) – Label of the progenitor/root cluster in adata.obs[obs_key]. Example: ‘17’ (leiden cluster 17)
branches (list of str) – Labels of the k terminal fate clusters. Example: [‘Monocyte’, ‘DC’, ‘Neutrophil’]
obs_key (str) – Column in adata.obs with cluster labels. Default: ‘leiden’.
n_angle_bins (int) – Number of angular bins for commitment scoring. Default: 36 (10° each).
sector_method ({'centroid', 'equal'}) –
How to define angular sectors: - ‘centroid’: anchor sectors to the direction from origin to each
fate centroid in the star embedding (recommended).
’equal’: divide [0°, 360°] into k equal sectors.
copy (bool) – Work on a copy of adata.
Examples
# k=2 bifurcation scorer = SingleScorer(
adata, root=’17’, branches=[‘homeostatic’, ‘activated’], obs_key=’leiden’,
) scorer.build_embedding(ordering_metric=’pseudotime’) scorer.fit() result = scorer.score() scorer.plot_star(result)
# k=3 with CytoTRACE2 scorer = SingleScorer(
adata, root=’5’, branches=[‘FateA’, ‘FateB’, ‘FateC’], obs_key=’cell_type’,
) scorer.build_embedding(ordering_metric=’cytotrace’) scorer.fit() result = scorer.score() scorer.plot_star(result)
- compute_velocity(mode: str = 'dynamical', n_top_genes: int = 2000, n_pcs: int = 30, n_neighbors: int = 30, min_shared_counts: int = 20, verbose: bool = True) SingleScorer[source]¶
Run the full scVelo RNA velocity pipeline.
Call this if adata does not yet have velocity vectors. Requires ‘spliced’ and ‘unspliced’ layers.
- Parameters:
mode ({'dynamical', 'stochastic', 'steady_state'})
n_top_genes (int)
n_pcs (int)
n_neighbors (int)
min_shared_counts (int)
verbose (bool)
- Return type:
self
- fit(verbose: bool = True) SingleScorer[source]¶
Build the FateMap from the user-supplied cluster labels.
Must be called after build_embedding().
This step: 1. Validates that root and branches
exist in adata.obs[obs_key].
Computes fate centroids in the X_sccs embedding.
Extracts velocity vectors if not already loaded.
- Return type:
self
- score(cell_mask: numpy.ndarray | None = None, cell_level: bool = True, k_nn: int | None = None, n_bootstrap: int = 0, bootstrap_ci: float = 0.95, bootstrap_seed: int = 42, verbose: bool = True, write_to_obs: bool = True) scCS.scores.CommitmentScoreResult[source]¶
Compute commitment scores for the full population or a subset.
- Parameters:
cell_mask (np.ndarray of bool, shape (n_sub_cells,), optional) – Boolean mask over
adata_subcells (NOT the full adata). If provided, only cells where mask=True contribute to the population-level score (M_bin, M_sector, unCS, nCS). Per-cell scores are still computed for all cells.cell_level (bool) – Whether to compute per-cell fate affinity scores.
k_nn (int, optional) – If set, compute NN-smoothed per-cell entropy using this many nearest neighbors in the scCS embedding (X_sccs).
n_bootstrap (int) – Number of bootstrap replicates for CS confidence intervals. 0 (default) disables bootstrapping. Recommended: 500.
bootstrap_ci (float) – Confidence interval level for bootstrap. Default 0.95 (95% CI).
bootstrap_seed (int) – Random seed for bootstrap resampling.
verbose (bool)
write_to_obs (bool) – If True (default), write per-cell scores to
adata_sub.obs.
- Return type:
- score_per_subset(split_by: str, cell_level: bool = False, n_bootstrap: int = 0, verbose: bool = False) dict[source]¶
Compute commitment scores separately for each value of split_by.
Useful for comparing commitment across conditions, time points, or trajectory directions.
- Parameters:
split_by (str) – Column in adata_sub.obs to split by.
cell_level (bool)
n_bootstrap (int) – Bootstrap replicates for CI. 0 = disabled.
verbose (bool)
- Return type:
dict mapping subset_value -> CommitmentScoreResult
- transfer_labels(adata, result: scCS.scores.CommitmentScoreResult, prefix: str = 'cs_') None[source]¶
Write per-cell commitment scores back to the full adata.
After scoring, per-cell fate affinities, dominant fate, and entropy are stored in
adata_sub.obs. This method transfers those columns to the full adata so they can be used in downstream analyses.Cells not in the embedding subset receive NaN for numeric columns and ‘unassigned’ for categorical columns.
- Parameters:
adata (AnnData) – The full dataset (same object passed to SingleScorer.__init__).
result (CommitmentScoreResult) – Output of scorer.score(cell_level=True).
prefix (str) – Column prefix. Default: ‘cs_’.
- save(path: str) None[source]¶
Serialize scorer state to a pickle file.
Saves the embedding, FateMap, velocity vectors, and configuration. The full
adatais NOT saved (too large); pass it again toload().- Parameters:
path (str) – Destination file path (e.g.,
'scorer.pkl').
- classmethod load(path: str, adata) SingleScorer[source]¶
Load a scorer from a pickle file.
- Parameters:
path (str) – Path to a file saved by
save().adata (AnnData) – The full dataset (same object originally passed to
SingleScorer.__init__). Not stored in the pickle.
- Return type:
- plot_star(result: scCS.scores.CommitmentScoreResult, **kwargs)[source]¶
Radial star embedding plot — primary visualization.
- plot_rose(result: scCS.scores.CommitmentScoreResult, **kwargs)[source]¶
Rose/polar plot of cumulative magnitudes per angular bin.
- plot_pairwise_cs(result: scCS.scores.CommitmentScoreResult, **kwargs)[source]¶
Heatmap of pairwise normalized commitment scores.
- plot_commitment_bar(result: scCS.scores.CommitmentScoreResult, **kwargs)[source]¶
Bar chart of unCS vs nCS per fate pair.
- plot_commitment_heatmap(result: scCS.scores.CommitmentScoreResult, **kwargs)[source]¶
Per-cell fate affinity heatmap.
- plot_subset_comparison(subset_results: dict, **kwargs)[source]¶
Compare commitment scores across subsets.
- plot_nn_entropy_elbow(**kwargs)[source]¶
Elbow plots for choosing k_nn for NN-smoothed entropy.
- Parameters:
k_nn_range (list or range, optional) – k_nn values to sweep. Default: range(5, 51, 5).
**kwargs – Passed to
scCS.plot.plot_nn_entropy_elbow().
- Returns:
fig
- Return type:
matplotlib Figure
- get_velocity_drivers(n_top_genes: int = 50) dict[source]¶
Rank genes by mean scVelo velocity in each fate arm.
- Parameters:
n_top_genes (int) – Number of top driver genes to print per fate.
- Returns:
dict
- Return type:
fate_name -> DataFrame[gene, mean_velocity, rank]
- get_deg_drivers(n_top_genes: int = 50, pval_threshold: float = 0.05, logfc_threshold: float = 0.25) dict[source]¶
Find DEGs for each fate arm vs the bifurcation cluster (Wilcoxon).
- Parameters:
n_top_genes (int)
pval_threshold (float)
logfc_threshold (float)
- Returns:
dict
- Return type:
fate_name -> DataFrame[gene, logfoldchange, pval, pval_adj, significant]
- get_velocity_fate_drivers(result: scCS.scores.CommitmentScoreResult, n_top_genes: int = 50, pval_threshold: float = 0.05) dict[source]¶
Identify driver genes by correlating gene velocity with fate affinity.
- Parameters:
result (CommitmentScoreResult) – Output of scorer.score(cell_level=True).
n_top_genes (int)
pval_threshold (float)
- Returns:
dict – mean_velocity, delta_velocity, significant]
- Return type:
fate_name -> DataFrame[gene, spearman_r, pval, pval_adj,
- get_enrichment(deg_drivers: dict, gene_sets: List[str] | None = None, organism: str = 'mouse', pval_threshold: float = 0.05, logfc_threshold: float = 0.25, plot: bool = True, n_top_pathways: int = 15) dict[source]¶
Run pathway enrichment on DEG driver genes per fate arm.
- Parameters:
deg_drivers (dict) – Output of get_deg_drivers().
gene_sets (list of str, optional)
organism (str)
pval_threshold (float)
logfc_threshold (float)
plot (bool)
n_top_pathways (int)
- Returns:
dict
- Return type:
fate_name -> {‘up’: DataFrame, ‘down’: DataFrame}