Skip to main content

pySCORPION

SCORPION (Single-Cell Oriented Reconstruction of PANDA Individually Optimized Gene Regulatory Networks) is a Python package for constructing gene regulatory networks from single-cell and single-nucleus RNA sequencing data. The package addresses the sparsity inherent in single-cell expression data through coarse-graining, which aggregates similar cells to improve correlation structure detection. Network reconstruction is performed using the PANDA (Passing Attributes between Networks for Data Assimilation) message-passing algorithm, integrating transcription factor motifs, protein-protein interactions, and gene expression data. By using consistent baseline priors across samples, SCORPION produces comparable, fully-connected, weighted regulatory networks suitable for population-level analyses.

method

Installation

pip install pyscorpion

To install the development version from GitHub:

pip install git+https://github.com/kuijjerlab/pySCORPION.git

Quick Start

from scorpion import load_example_data, scorpion, run_scorpion

# Load the bundled example dataset
data = load_example_data()

# Construct a single regulatory network
network = scorpion(
    gex_matrix=data["gex_matrix"],
    tf_motifs=data["tf_motifs"],
    ppi_net=data["ppi_net"],
)

# Construct networks stratified by cell groups
networks = run_scorpion(
    gex_matrix=data["gex_matrix"],
    tf_motifs=data["tf_motifs"],
    ppi_net=data["ppi_net"],
    cells_metadata=data["metadata"],
    group_by="region",
)

Example Data

The package ships with a colorectal cancer single-cell RNA-seq dataset (300 genes, ~1 950 cells, 3 donors, 3 tissue regions) that can be loaded with a single call:

from scorpion import load_example_data

data = load_example_data()

data["gex_matrix"]   # Gene expression matrix (genes × cells)
data["tf_motifs"]    # TF–target motif prior network
data["ppi_net"]      # Protein–protein interaction network
data["metadata"]     # Cell-level metadata (cell_id, donor, region, cell_type)

Core Functions

scorpion

Constructs a single gene regulatory network from a gene expression matrix using coarse-graining and the PANDA algorithm.

Usage:

result = scorpion(
    gex_matrix=expression_data,
    tf_motifs=None,
    ppi_net=None,
    computing_engine="cpu",
    n_cores=1,
    gamma_value=10,
    n_pc=25,
    assoc_method="pearson",
    alpha_value=0.1,
    hamming_value=0.001,
    n_iter=float("inf"),
    out_net=["regNet", "coregNet", "coopNet"],
    z_scaling=True,
    show_progress=True,
    randomization_method=None,
    scale_by_present=False,
    filter_expr=False,
    random_state=None,
    gene_names=None,
)

Parameters:

Parameter Description Default
gex_matrix Expression matrix with genes in rows and cells in columns Required
tf_motifs DataFrame with columns [TF, target gene, motif score]. Pass None for co-expression analysis only None
ppi_net DataFrame with columns [protein1, protein2, interaction score]. Pass None to disable PPI integration None
computing_engine Computation backend: "cpu" or "gpu" (GPU is not implemented in Python; falls back to CPU with a warning) "cpu"
n_cores Number of processors for BLAS/MPI parallel computation 1
gamma_value Coarse-graining level; ratio of cells to super-cells 10
n_pc Number of principal components for kNN network construction 25
assoc_method Gene association method: "pearson", "spearman", or "pcNet" "pearson"
alpha_value Weight of prior networks relative to expression data (0–1) 0.1
hamming_value Convergence threshold based on Hamming distance 0.001
n_iter Maximum number of PANDA iterations before stopping inf
out_net Networks to return: "regNet", "coregNet", and/or "coopNet" All three
z_scaling Return Z-score normalized edge weights; False returns [0,1] scale True
show_progress Print progress messages during computation True
randomization_method Randomization for null models: None, "within.gene", or "by.gene" (underscore spellings also accepted) None
scale_by_present Scale correlations by percentage of cells with non-zero expression False
filter_expr Remove genes with zero expression across all cells before inference False
random_state Random seed for reproducibility None
gene_names Array of gene names; if None, inferred from the expression matrix None

Return value:

A dictionary containing:

Component Description
regNet Regulatory network matrix (TFs × target genes)
coregNet Co-regulation network matrix (genes × genes)
coopNet TF cooperative network matrix (TFs × TFs)
numGenes Number of genes in the network
numTFs Number of transcription factors
numEdges Total number of edges in the regulatory network

When both tf_motifs and ppi_net are None, scorpion() returns the gene-gene co-expression matrix of the super-cells as a DataFrame.


run_scorpion

Constructs regulatory networks for multiple cell groups defined by metadata columns. This function wraps scorpion() to enable stratified network inference and returns results in a format suitable for comparative analysis.

Usage:

networks = run_scorpion(
    gex_matrix=expression_data,
    tf_motifs=motif_prior,
    ppi_net=ppi_network,
    cells_metadata=metadata,
    group_by="region",
    normalize_data=True,
    remove_batch_effect=False,
    batch=None,
    min_cells=30,
)

Parameters:

Parameter Description Default
gex_matrix Expression matrix with genes in rows and cells in columns Required
tf_motifs DataFrame with columns [TF, target gene, motif score] Required
ppi_net DataFrame with columns [protein1, protein2, interaction score] Required
cells_metadata DataFrame with cell-level metadata; must contain columns specified in group_by Required
group_by String or list of column name(s) in cells_metadata for stratification Required
normalize_data Apply log normalization to expression data before network inference True
remove_batch_effect Perform batch effect correction before network inference False
batch Batch assignment for each cell, as a per-cell vector or a column name in cells_metadata; required if remove_batch_effect=True. The per-gene median is added back after correction; with a single batch level, correction is skipped None
min_cells Minimum number of cells required per group to build a network (values below 30 are raised to 30) 30
n_cores Number of worker processes used to build the group networks in parallel 1
out_net Network(s) to extract: "regNet", "coregNet", "coopNet", or a list of them "regNet"

Additional parameters: All other scorpion() parameters (computing_engine, gamma_value, n_pc, assoc_method, alpha_value, hamming_value, n_iter, z_scaling, show_progress, randomization_method, scale_by_present, filter_expr) can be passed to control network inference behavior. See scorpion() documentation above.

Return value:

A DataFrame in wide format where:

  • Rows represent TF-target pairs (the full grid over the union of all networks' TFs and targets)
  • Columns represent network identifiers (derived from group_by values, in order of first appearance)
  • Values are edge weights from each network; pairs absent from a group's network are NaN
  • When several networks are requested in out_net, a leading edge_type column ("tf-target", "gene-gene", "tf-tf") is added and the network types are stacked

Example output:

tf target P31--T P31--B P31--N P32--T ...
AATF ACKR1 -0.326 -0.337 -0.344 -0.298 ...
ABL1 ACKR1 -0.340 -0.339 -0.351 -0.312 ...

Examples:

from scorpion import load_example_data, scorpion, run_scorpion

# Load example data
data = load_example_data()

# Stratify by tissue region
nets_by_region = run_scorpion(
    gex_matrix=data["gex_matrix"],
    tf_motifs=data["tf_motifs"],
    ppi_net=data["ppi_net"],
    cells_metadata=data["metadata"],
    group_by="region",
)

# Stratify by multiple variables
nets_by_donor_region = run_scorpion(
    gex_matrix=data["gex_matrix"],
    tf_motifs=data["tf_motifs"],
    ppi_net=data["ppi_net"],
    cells_metadata=data["metadata"],
    group_by=["donor", "region"],
)

# With batch effect correction
nets_corrected = run_scorpion(
    gex_matrix=data["gex_matrix"],
    tf_motifs=data["tf_motifs"],
    ppi_net=data["ppi_net"],
    cells_metadata=data["metadata"],
    group_by="region",
    remove_batch_effect=True,
    batch="donor",
)

Statistical Analysis

test_edges

Performs statistical testing on network edges to identify differential regulatory relationships between groups. The function supports single-sample tests, two-sample comparisons, and paired tests. All computations are fully vectorized for efficiency with large-scale datasets.

Usage:

results = test_edges(
    networks_df=nets,
    test_type="single",
    group1=tumor_nets,
    group2=None,
    paired=False,
    alternative="two.sided",
    padjust_method="BH",
    min_log2fc=0.0,
    moderate_variance=True,
    empirical_null=True,
    n_cores=1,
    batch_size=None,
)

Parameters:

Parameter Description Default
networks_df Output from run_scorpion() Required
test_type Test type: "single" (one-sample) or "two.sample" Required
group1 List of column names for the first (or only) group Required
group2 List of column names for the second group (two-sample tests) None
paired Perform paired t-test; requires equal-length groups in matched order False
alternative Alternative hypothesis: "two.sided", "greater", or "less" "two.sided"
padjust_method Multiple testing correction, as in R's p.adjust: "holm", "hochberg", "hommel", "bonferroni", "BH", "BY", "fdr", "none" "BH"
min_log2fc Minimum absolute log2 fold change for inclusion (two-sample/paired only) 0.0
moderate_variance Apply SAM-style variance moderation; adds median(SE) to denominator True
empirical_null Use Efron's empirical null (median/MAD) for p-value calibration True
n_cores Number of parallel workers; edges are processed in batches and the moderation factor is computed once over all edges 1
batch_size Edges per batch when n_cores > 1; None uses ceil(n_edges / n_cores) None

Return value:

A DataFrame containing:

Column Description
tf, target TF-target pair identifiers
meanGroup1, meanGroup2 Group means (two-sample)
cohensD Cohen's d effect size (two-sample and paired tests)
log2FoldChange Difference in mean edge weight, Group1 − Group2 (two-sample)
meanEdge Mean edge weight
SE Raw, unmoderated standard error (input for ma_edges())
tStatistic t-statistic
pValue Raw p-value
pAdj Adjusted p-value

Examples:

from scorpion import test_edges

# Define groups
tumor_nets = [c for c in nets_by_donor_region.columns if c.endswith("--T")]
normal_nets = [c for c in nets_by_donor_region.columns if c.endswith("--N")]

# Two-sample comparison: Tumor vs Normal
results = test_edges(
    networks_df=nets_by_donor_region,
    test_type="two.sample",
    group1=tumor_nets,
    group2=normal_nets,
)

# Paired test for matched samples (same patient)
tumor_ordered = ["P31--T", "P32--T", "P33--T"]
normal_ordered = ["P31--N", "P32--N", "P33--N"]

results_paired = test_edges(
    networks_df=nets_by_donor_region,
    test_type="two.sample",
    group1=tumor_ordered,
    group2=normal_ordered,
    paired=True,
)

# Single-sample test: edges differing from zero
results_single = test_edges(
    networks_df=nets_by_region,
    test_type="single",
    group1=tumor_nets,
)

regress_edges

Performs linear regression to identify edges with significant trends across ordered conditions. This is useful for studying disease progression or developmental trajectories.

Usage:

results = regress_edges(
    networks_df=nets,
    ordered_groups=ordered_conditions,
    padjust_method="BH",
    min_mean_edge=0.0,
)

Parameters:

Parameter Description Default
networks_df Output from run_scorpion() Required
ordered_groups Dictionary where each value is a list of column names in networks_df. Keys represent ordered conditions (e.g., {"Normal": [...], "Border": [...], "Tumor": [...]}). The order of keys defines the progression Required
padjust_method Multiple testing correction method "BH"
min_mean_edge Minimum mean absolute edge weight for inclusion 0.0

Return value:

A DataFrame containing:

Column Description
tf, target TF-target pair identifiers
slope Regression slope (change per condition step)
intercept Regression intercept
rSquared Coefficient of determination
fStatistic F-statistic for the regression
pValue Raw p-value
pAdj Adjusted p-value
meanEdge Overall mean edge weight
mean<Condition> Mean edge weight for each condition

Example:

from scorpion import regress_edges

# Define ordered progression: Normal → Border → Tumor
normal_nets = [c for c in nets_by_donor_region.columns if c.endswith("--N")]
border_nets = [c for c in nets_by_donor_region.columns if c.endswith("--B")]
tumor_nets = [c for c in nets_by_donor_region.columns if c.endswith("--T")]

ordered_conditions = {
    "Normal": normal_nets,
    "Border": border_nets,
    "Tumor": tumor_nets,
}

# Identify edges with significant trends
results_reg = regress_edges(
    networks_df=nets_by_donor_region,
    ordered_groups=ordered_conditions,
)

# Edges increasing along progression
increasing = results_reg[(results_reg["pAdj"] < 0.05) & (results_reg["slope"] > 0)]

# Edges decreasing along progression
decreasing = results_reg[(results_reg["pAdj"] < 0.05) & (results_reg["slope"] < 0)]

ma_edges

Performs a meta-analysis of TF-target edges across studies using either a DerSimonian-Laird random-effects or an inverse-variance fixed-effect model. Each study is typically a test_edges() result. A study contributes to a TF-target pair only when both its effect size and SE are valid.

Usage:

meta = ma_edges(
    edges_list=[study1, study2, study3],
    method="random",
    min_studies=2,
    padjust_method="BH",
    moderate_variance=True,
    s0=None,
)

Parameters:

Parameter Description Default
edges_list List (or dict) of DataFrames with columns tf, target, log2FoldChange and SE; at least two Required
method "random" (DerSimonian-Laird) or "fixed" (inverse-variance) "random"
min_studies Minimum number of studies with valid data for a TF-target pair to be included 2
padjust_method Multiple testing correction method (as in test_edges()) "BH"
moderate_variance Apply SAM-style moderation to the meta-analysis SE True
s0 Moderation fudge factor; None uses the median of all meta-analysis SEs None

Return value:

A DataFrame sorted by tf and target containing:

Column Description
tf, target TF-target pair identifiers
k Number of contributing studies
log2FoldChange Meta-analytic effect size
SE Meta-analysis standard error (unmoderated)
ciLow, ciHigh 95% confidence interval
zStatistic Test statistic
pValue, pAdj Raw and adjusted p-values
Q Cochran's Q heterogeneity statistic
iSquared I² heterogeneity (percentage)
tauSquared DerSimonian-Laird between-study variance

Example:

from scorpion import test_edges, ma_edges

study1 = test_edges(nets_cohort1, test_type="two.sample", group1=t1, group2=n1)
study2 = test_edges(nets_cohort2, test_type="two.sample", group1=t2, group2=n2)

meta = ma_edges([study1, study2], method="random")

Dependencies

  • NumPy (>=1.21)
  • pandas (>=1.3)
  • SciPy (>=1.7)
  • scikit-learn (>=1.0)
  • igraph (>=0.10)

Citation

If you use SCORPION in your research, please cite:

Osorio, D., Capasso, A., Eckhardt, S.G. et al. Population-level comparisons of gene regulatory networks modeled on high-throughput single-cell transcriptomics data. Nature Computational Science 4, 237–250 (2024). https://doi.org/10.1038/s43588-024-00597-5


Additional Resources

Metadata

Release files for pyscorpion 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pyscorpion 0.2.0
File Size Uploaded
pyscorpion-0.2.0.tar.gz 1.5 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for pyscorpion 0.2.0
File Interpreter ABI Platform
pyscorpion-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 3.0 MB

Release files / pyscorpion-0.2.0.tar.gz

Download URL pyscorpion-0.2.0.tar.gz
Size 1.5 MB
Tags Source
SHA-256 checksum
How to use checksums
bf0ca86a2bc6139b55bd4cf933ae643d2b899d8c90732b112084c4de1434ba08
BLAKE2b-256 checksum
How to use checksums
03e3cb8310c56e6d544a0223c96afb89097afbbba6d47e2a513c54bc5d4f32b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release files / pyscorpion-0.2.0-py3-none-any.whl

Download URL pyscorpion-0.2.0-py3-none-any.whl
Size 1.5 MB
Tags Python 3
SHA-256 checksum
How to use checksums
e18231e36c5392526dfe93751c14b00cfb85aa50a6fd435b21584b27f5316178
BLAKE2b-256 checksum
How to use checksums
52f8a7b6f0bd6fe936a0bd26fb92bd1f646050b026eace52050efd11b6c00cd4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 29, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release 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