Skip to main content

pysigscore

PyPI version Python 3.10 Python 3.12 License: Apache 2.0

pysigscore is a Python framework for computing and comparing gene signature scores in bulk and single-cell transcriptomics data. It also evaluates score significance and signature robustness and provides plotting utilities for result comparison.


Features

  • 18 built-in scores: 14 direct statistics, one Z-score, and three rank-based methods (AUCell, ssGSEA, and GSVA).
  • Custom scorer: supply your own scoring function and compare it with the built-in methods.
  • Flexible transformation pipelines: log, min-max scale, standardisation, KNN smoothing, step, and quantile normalisation — composable as ordered pipelines.
  • Permutation and analytical p-values: assess significance of each computed score.
  • Leave-one-out (LOO) robustness experiments: show robustness of each gene signature.
  • Summary metrics and visualisation: histograms, boxplots, violin plots, heatmaps, cross-scorer comparisons, sample-set comparisons and statistical test plots.
  • HDF5 serialisation: save and reload the object to restart the analysis.

Installation

From source (development)

git clone https://github.com/bioinformatics-hub/pysigscore.git
cd pysigscore
pip install -e ".[full, dev]"

Core dependencies

Installed automatically:

numpy>=1.23
scipy>=1.9
pandas>=1.5
anndata>=0.9
scikit-learn>=1.1
numba>=0.56
h5py>=3.7
matplotlib>=3.5
seaborn>=0.12

Optional dependencies

Extra Methods unlocked Install command
aucell AUCell pip install -e ".[aucell]"
gsea ssGSEA, GSVA pip install -e ".[gsea]"
full aucell + gsea pip install -e ".[full]"
test pytests pip install -e ".[test]"
dev dev libraries + test pip install -e ".[dev]"

Version details in pyproject.toml


Quick Start

import anndata as ad
from pysigscore import Scorer, configure_logging

# Optional: show progress messages during computations
configure_logging()

# ── 1. Prepare data (cells × genes AnnData) ─────────────────────────────────
adata = ad.read_h5ad("your_data.h5ad")   # rows = cells/samples, cols = genes

# ── 2. Initialise scorer ────────────────────────────────────────────────────
scorer = Scorer(
    random_state=42,
    name="MyProject",     # output folder name
    path=".",             # parent directory
)

# ── 3. Import expression data ──────────────────────────────────────────────
scorer.import_adata(adata)
# or from a DataFrame:
# scorer.import_adata_as_dataframe(df, cluster=cluster_labels)

# ── 4. Import gene sets ────────────────────────────────────────────────────
geneset_dict = {
    "Hallmarks_1": ["VEGFA", "GAPDH", "SLC2A1"],
    "Hallmarks_2":  ["MDM2", "CDKN1A", "BBC3"],
}
scorer.import_geneset_dict(geneset_dict, keys="genesets")

# ── 5. Compute enrichment scores ───────────────────────────────────────────
scorer.compute_scores(
    transform_list_data=["raw", "log"],      # score raw and log-transformed expression
    transform_list_enrich=["raw"],            # keep score matrices untransformed
    enrich_grid={
        "Mean":   {"remove_na": True},
        "Median": {"remove_na": True},
        "Z":      {"remove_na": True, "ddof": 0},
    },
    p_value_grid={                           # 1,000 permutation p-values for Mean/Median;
        "Mean": 1000,                       # analytical two-sided normal p-values for Z
        "Median": 1000,
        "Z": True,
    },
    loo_grid={"Median": ["log"]},           # LOO errors for Median on log-transformed data
    geneset_list_loo_genewise=["Hallmarks_1"],
)
# CSV files are saved under MyProject/<ScoreName>/.

# ── 6. Return results of objects of interest ───────────────────────────────

# Return computed matrices
results = scorer.return_values(
    value="score",
    enrich=["Mean"],
    data_trans=["raw"],
    enrich_trans=["raw"],
    geneset_list=["Hallmarks_1"],
    samples_list=None,  # use all samples
)

# ── 7. Compute Summary Metrics ──────────────────────────────────────────────

# Compute one mean Z score for Hallmarks_2 across all samples
metrics = scorer.return_metrics(
    value="score",
    metric="mean",
    enrich=["Z"],
    axis=0,
    data_trans=["raw"],
    enrich_trans=["raw"],
    geneset_list=["Hallmarks_2"],
    samples_list=None,
    return_results=True,
)
# Saved as MyProject/Z/metrics/Z_score_mean.csv

API Overview

Scorer class

Scorer(random_state=42, name='Project01', path=None, dtype=None)
Method Description
import_adata(adata, cluster_column_name=None) Load a samples × genes AnnData object; optional cluster labels
import_adata_as_dataframe(df, cluster=None) Load a samples × genes DataFrame; optional cluster labels
import_geneset_dict(geneset_info, keys='genesets', ...) Load gene sets from a dict
import_geneset_matrix(geneset_info, ...) Load gene sets from a binary DataFrame or ndarray
import_geneset_matrix_from_celloracle(base_GRN, ...) Load from a CellOracle base GRN DataFrame
compute_scores(...) Compute selected scores for each requested transformation, with optional p-values and LOO errors
return_values(value, enrich, data_trans, enrich_trans, ...) Return selected result matrices as {csv_stem: DataFrame}
return_metrics(value, metric, ...) Save summary metric CSVs and optionally return them
plot_values(value, method, ...) Save histogram, boxplot, violin or scatter plots
plot_heatmap(value, ...) Save heatmaps of score, pvalue or LOO matrices
plot_heatmap_loo_genewise(enrich, ...) Plot gene-wise LOO errors and optionally return the matrices
plot_heatmap_corr(value, ...) Save geneset correlation heatmaps of scores, pvalues or LOO matrices
plot_comparison_distribution(...) Compare score, p-value, or LOO distributions across scoring methods
plot_cross_scorer_corr(...) Plot cross-scorer correlation for one gene set
plot_distribution_sampleset(...) Compare one geneset across multiple sample groups
stat_test_geneset_between_samples(...) Mann–Whitney U comparison between two sample groups
stat_test_samples_between_genesets(...) Mann–Whitney U comparison between two genesets
to_hdf5(file_path) Serialise the Scorer to HDF5 (.pysigscore.object)

Use the module-level load_pysigscore(file_path) function to restore a saved Scorer object.

Supported Data Transformations

Data and post enrichment transformations are the following:

Transformation Description
raw No transformation
log Either ln(1+x) or log2(1+x)
scale min-max scale
standard Standard-deviation or MAD scaling, with optional centring
KNN CellOracle KNN smoothing
quantile Equalise data distributions across genes or samples
step Apply step thresholding to the data

Transformations can be composed as space-separated names, such as "log KNN standard" or "log scale"; "raw" must be used alone. The default parameters can be overridden with transform_hyper:

transform_hyper = {"log": {"type": "natural_log"},
                          "KNN": {"div_by_std": False, "max_n_components": 50,
                                  "pca_curvature": 0.002, "k": None,
                                  "metric": "euclidean", "diag": 1.0,
                                  "n_pca_dims": None, "b_sight": None,
                                  "b_maxl": None, "group_constraint": None,
                                  "n_jobs": -1},
                           "scale": {"feature_range": (0,1),"axis_scale": 0},
                           "standard": {"subtract": False, "robust": False, "axis_standard": 0},
                           "step": {"y": (-1.0, 0.0, 1.0), "thr": None,
                                    "method": "median", "axis_step": 0},
                           "quantile": {"kind": "mergesort", "axis_quantile": 0}}

Supported enrichment scores

Score Key Description
Sum 'Sum' Sum of all values in the signature
Weighted Sum 'WeightedSum' Sum with gene-specific weights
Mean 'Mean' Arithmetic average of values in the signature
Weighted Mean 'WeightedMean' Mean after applying gene-specific weights
Median 'Median' Median of all values in the signature
Trimmed Mean 'TrimmedMean' Mean after removing extreme values of signature genes
Mode 'Mode' Most frequent value in the signature
Mid-Range 'MidRange' Average of min and max values in the signature
Mid-Hinge 'MidHinge' Average of first and third quartiles in the signature
Tukey Trimean 'TriMean' Weighted average of median and quartiles in the signature
IQR 'IQR' Interquartile range (Q3 − Q1) of values in the signature
IQM 'IQM' Mean of values within the IQR in the signature
MAD 'MAD' Median absolute deviation of signature genes
AAD 'AAD' Average absolute deviation of signature genes
Z-score 'Z' Signature mean relative to the sample-wide mean and standard deviation
AUCell 'Aucell' AUC-based gene set activity score
ssGSEA 'ssGSEA' Single-sample GSEA enrichment score
GSVA 'GSVA' Non-parametric gene set variation score
Custom 'Custom' User-defined scoring function

Pass only the methods to run in enrich_grid; omitted parameters use the defaults shown below.

enrich_grid = {
    "Sum":         {"remove_na": True},
    "WeightedSum": {"remove_na": True},
    "Mean":        {"remove_na": True},
    "WeightedMean":{"remove_na": True},
    "Median":      {"remove_na": True},
    "TrimmedMean": {"remove_na": True, "quantile": 0.05},
    "Mode":        {"remove_na": True},
    "MidRange":    {"remove_na": True},
    "MidHinge":    {"remove_na": True},
    "TriMean":     {"remove_na": True},
    "IQR":         {"remove_na": True},
    "IQM":         {"remove_na": True},
    "MAD":         {"remove_na": True},
    "AAD":         {"remove_na": True},
    "Z":           {"remove_na": True, "ddof": 0},
    "Aucell":      {"auc_threshold": 0.05, "noweights": False},
    "ssGSEA":      {"sample_norm_method": "rank", "correl_norm_type": "rank",
                    "min_size": None, "max_size": None, "weight": 0,
                    "ascending": False, "NES": True, "p_val": "NOM p-val"},
    "GSVA":        {"min_size": None, "max_size": None, "weight": 0,
                    "kcdf": None, "mx_diff": True, "abs_rnk": False},
    "Custom":      {"custom_func": None, "custom_pval": None},
}

Custom scorer

A custom scorer receives arr_geneset, containing the signature-gene values for one sample, and arr_full, containing all gene values for that sample. It must return one numeric score.

def custom_score_example(arr_geneset, arr_full):
    return float(arr_geneset.max() - arr_geneset.min())

scorer.compute_scores(
    enrich_grid={"Custom": {"custom_func": custom_score_example}},
)

Summaries

return_metrics summarises saved score, p-value, or average LOO matrices using the mean, median, standard deviation, or coefficient of variation (cv). Use axis=0 to summarise each gene set across samples and axis=1 to summarise each sample across gene sets. Results are saved in <path>/<name>/<ScoreName>/metrics/; set return_results=True to also return them as {csv_stem: DataFrame}.


Plotting

Single-matrix visualisation

plot_values creates histograms, boxplots, violin plots, or scatter plots from one saved matrix. axis=0 plots each gene set across samples, axis=1 plots each sample across gene sets, and whole=True plots all entries together. plot_heatmap displays a selected matrix, while plot_heatmap_loo_genewise displays the error caused by removing each gene from a signature. PDFs are saved in <path>/<name>/<ScoreName>/plots/.

# Distribution of one gene set across samples
scorer.plot_values(
    value="score",
    method="boxplot",
    enrich=["Median"],
    data_trans=["log"],
    enrich_trans=["raw"],
    geneset_list=["Hallmarks_1"],
    axis=0,
    name="per_geneset",
)

# Full score matrix
scorer.plot_heatmap(
    value="score",
    enrich=["Mean"],
    data_trans=["raw"],
    enrich_trans=["raw"],
    geneset_list=["Hallmarks_1", "Hallmarks_2"],
    name="scores",
)

# Per-gene LOO errors computed in the Quick Start
scorer.plot_heatmap_loo_genewise(
    enrich=["Median"],
    data_trans=["log"],
    geneset_list=["Hallmarks_1"],
    name="loo",
)

Multiple-matrix comparisons

Method Purpose
plot_comparison_distribution Compare one gene set's distribution across scoring methods
plot_cross_scorer_corr Correlate scoring methods across samples for one gene set
plot_distribution_sampleset Compare one gene set across user-defined sample groups
stat_test_geneset_between_samples Test whether the first sample group has lower values than the second
stat_test_samples_between_genesets Test whether the first gene set has lower values than the second

The two statistical methods use a one-sided Mann–Whitney U test, so group or gene-set order matters. All comparison plots are saved in <path>/<name>/Comparisons/.

groups = {
    # Replace these placeholders with sample IDs from scorer.samples.
    "Control": ["Cell_1", "Cell_2"],
    "Treatment": ["Cell_3", "Cell_4"],
}

scorer.plot_comparison_distribution(
    value="score", method="boxplot",
    enrich=["Mean", "Median", "Z"],
    data_trans="raw", enrich_trans="raw",
    geneset="Hallmarks_1", name="scorer_distribution",
)

scorer.plot_cross_scorer_corr(
    value="score", enrich=["Mean", "Median", "Z"],
    data_trans="raw", enrich_trans="raw",
    geneset="Hallmarks_1", samples_list=None,
    corr_method="spearman", name="scorer_corr",
)

scorer.plot_distribution_sampleset(
    value="score", method="violinplot", enrich="Mean",
    data_trans="raw", enrich_trans="raw",
    geneset="Hallmarks_1", samples_dict=groups,
    name="sample_groups",
)

scorer.stat_test_geneset_between_samples(
    value="score", method="boxplot", enrich="Mean",
    data_trans="raw", enrich_trans="raw",
    geneset="Hallmarks_1", samples_dict=groups,
    name="sample_test",
)

scorer.stat_test_samples_between_genesets(
    value="score", method="boxplot", enrich="Mean",
    data_trans="raw", enrich_trans="raw",
    geneset_list=["Hallmarks_1", "Hallmarks_2"],
    samples_list=None, name="geneset_test",
)

Output Structure

Each scorer stores its matrices, metrics, and plots under <path>/<name>/<ScoreName>/. Cross-scorer and sample-group comparisons are stored under <path>/<name>/Comparisons/. The examples above produce the following main files (... represents the compared labels inserted into statistical-test filenames):

MyProject/
    Mean/
        scores/
            Mean_score_Data_raw_Enrich_raw.csv
            Mean_score_Data_log_Enrich_raw.csv
        pvalues/
            Mean_pvalue_Data_raw_n_perm_1000.csv
            Mean_pvalue_Data_log_n_perm_1000.csv
        plots/
            Heatmap_Mean_score_Data_raw_Enrich_raw_scores.pdf
    Median/
        scores/
            Median_score_Data_raw_Enrich_raw.csv
            Median_score_Data_log_Enrich_raw.csv
        pvalues/
            Median_pvalue_Data_raw_n_perm_1000.csv
            Median_pvalue_Data_log_n_perm_1000.csv
        loo_average/
            Median_loo_Data_log_Metric_MAE.csv
        loo_genewise/
            Median_loo_genewise_Hallmarks_1_Data_log_Metric_MAE.csv
        plots/
            BoxPlot_Median_score_Data_log_Enrich_raw_Hallmarks_1_per_geneset.pdf
            Heatmap_Median_loo_genewise_Hallmarks_1_Data_log_Metric_MAE_loo.pdf
    Z/
        scores/
            Z_score_Data_raw_Enrich_raw.csv
            Z_score_Data_log_Enrich_raw.csv
        pvalues/
            Z_pvalue_Data_raw.csv
            Z_pvalue_Data_log.csv
        metrics/
            Z_score_mean.csv
    Comparisons/
        CompDist_score_Data_raw_Enrich_raw_Hallmarks_1_scorer_distribution.pdf
        CrossScorerCorr_score_Data_raw_Enrich_raw_Hallmarks_1_scorer_corr.pdf
        DistrSampleSet_Mean_score_Data_raw_Enrich_raw_Hallmarks_1_sample_groups.pdf
        MW_SampleSet_Mean_score_Data_raw_Enrich_raw_..._sample_test.pdf
        MW_Genesets_Mean_score_Data_raw_Enrich_raw_..._geneset_test.pdf

Score matrices, p-value matrices, and average LOO matrices have samples/cells as rows and gene sets as columns. Gene-wise LOO files have samples/cells as rows and genes from one selected gene set as columns.


Notes

  • KNN smoothing requires enough cells to produce a meaningful neighbourhood graph.
  • LOO experiments become more expensive as the number of samples and signature genes grows; rank-based methods can be especially slow.

Code Matters

Small parts of the code, explicitly cited, are inspired by these two libraries:

Claude Code Sonnet 4.6 was also used for code review and documentation. All AI-written code was manually reviewed and tested.


pysigQC-metrics

As an optional step, pysigQC can be used before scoring to assess how well each gene set is represented in the input expression data:


Citation

If you use pysigscore in your research, please cite:

@article{10.1093/bioadv/vbag021,
        author = {Barberis, Alessandro and Buffa, Francesca M},
        title = {Sigscores: summary scores for molecular signatures in R},
        journal = {Bioinformatics Advances},
        volume = {6},
        number = {1},
        pages = {vbag021},
        year = {2026},
        month = {01},
        issn = {2635-0041},
        doi = {10.1093/bioadv/vbag021},
        url = {https://doi.org/10.1093/bioadv/vbag021},
    }

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pysigscore-0.1.0.tar.gz (95.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pysigscore-0.1.0-py3-none-any.whl (63.7 kB view details)

Uploaded Python 3

File details

Details for the file pysigscore-0.1.0.tar.gz.

File metadata

  • Download URL: pysigscore-0.1.0.tar.gz
  • Upload date:
  • Size: 95.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for pysigscore-0.1.0.tar.gz
Algorithm Hash digest
SHA256 e4f39d67a511753dab32d0ccdeabf0083cf8fa675b3f54ee6ce690cda4733af6
MD5 ba83ca4899cd677a72d641f6fafcbc4b
BLAKE2b-256 14248f9398d8e0be470c74ba44fefb040a75c25fc4ca201b7e11d355a0047383

See more details on using hashes here.

File details

Details for the file pysigscore-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: pysigscore-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 63.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.13

File hashes

Hashes for pysigscore-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0c2f4675e35143a0b9eb0516228fd475a1ff86d57c87c630977c1db2c032a20f
MD5 bbd3df0527a538503c8f4782eff4fd27
BLAKE2b-256 191ac4e3173da29c72644779339d2fd1f7d5470687ededc9e7ae5bd1f80dde3e

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page