rust-scHiCluster
Rust re-implementation of the inner numerical pipeline of scHiCluster (Zhou et al. 2019, PNAS) — single-cell Hi-C contact-matrix imputation. ~10× faster on long chromosomes at single-cell impute, bit-equivalent within float-32 epsilon.
This is a separate package that re-implements the algorithm in Rust;
it is not a fork of the upstream Python tree. The original Python
implementation continues to be available as pip install schicluster
(and is used here only as the parity baseline in the test suite).
What it computes
schicluster_rs.impute_chromosome(...) runs the same end-to-end
pipeline as schicluster.impute.impute_chromosome.impute_chromosome:
- Read raw single-cell contact matrix from a
.coolfile. - Drop the diagonal.
- 2-D Gaussian convolution (mirror padding) — replaces
scipy.ndimage.gaussian_filter. - Drop the diagonal again.
- Row-normalise → P.
- Random-walk-with-restart fixed point:
Q = (1−rp)·P·Q + rp·Pfor up to 30 iterations or until ‖Q_t − Q_{t-1}‖_F < tol. - Symmetrise:
E = Q + Qᵀ. - SQRTVC normalise:
E ← D^{-1/2} · E · D^{-1/2}whereD = diag(Eᵀ𝟙). - Filter the upper triangle to entries with
j − i ≤ output_dist_bins. - Write the result to an HDF5 file (cooler-compatible).
Steps 2–9 run inside Rust; only the cooler read in step 1 and the HDF5 write in step 10 cross the Python boundary.
Speed
Real Chang 2024 LC462 mouse cortex Droplet Hi-C, 25 kb resolution:
| step | scipy upstream | rust | speedup |
|---|---|---|---|
| chr1 (n = 7820 bins) | 30.5 s | 3.2 s | 9.6× |
| chr19 (n = 2461 bins) | 0.4 s | 0.27 s | 1.5× |
| 20 chrs end-to-end per cell | 87 s | 33 s | 2.7× |
Multi-process parallelism (8 workers × 2 rayon threads = 16 cores total): 8 chr1 in parallel from 29 s → 9.4 s = an additional 3.1× beyond the per-cell speedup, by avoiding rayon thread oversubscription.
Accuracy
Bit-equivalent to upstream within float-32 ε. On real Chang chr1 (n = 7820, ~1.7 M output non-zeros):
max |E_rust − E_scipy|=8.94 × 10⁻⁸- Pearson correlation =
1.000000 - nnz match exactly.
tests/test_parity.py runs random_walk_cpu over (n, rp) ∈
{50, 200, 500} × {0.05, 0.5, 0.9} and asserts max-relative-error < 1e-4
against scipy's reference implementation. All 11 tests pass.
Install
Requires Rust ≥ 1.78 and maturin ≥ 1.4:
git clone https://github.com/omicverse/rust-scHiCluster
cd rust-scHiCluster
maturin develop --release # build + install into the active venv
Or from PyPI (Linux x86_64 manylinux2014, CPython 3.10):
pip install schicluster-rs
Other platforms install from sdist and require Rust ≥ 1.78 in the build environment. Pre-built wheels for Python 3.9–3.13 across linux/macOS/Windows will be added via cibuildwheel.
Use
Drop-in monkey-patch (recommended) — no code changes anywhere:
import schicluster_rs
schicluster_rs.set_num_threads(2) # 8 workers × 2 = 16 cores
schicluster_rs.patch_schicluster()
# every downstream call to scHiCluster's impute_chromosome now uses Rust:
from schicluster.impute.impute_chromosome import impute_chromosome
impute_chromosome(scool_url=..., chrom='chr1', resolution=25_000,
output_path=..., rp=0.5, tol=0.01,
pad=1, std=1.0, output_dist=10_050_000)
Direct:
from schicluster_rs import random_walk_cpu, impute_chromosome
# Just the iterative RWR step (CSR → CSR):
Q = random_walk_cpu(P, rp=0.5, tol=0.01)
# Full inner pipeline (writes HDF5 like upstream):
impute_chromosome(scool_url='cell.cool', chrom='chr1',
resolution=25_000, output_path='chr1.hdf',
rp=0.5, tol=0.01, pad=1, std=1.0,
output_dist=10_050_000)
Multi-process tuning
schicluster's default workflow is ProcessPoolExecutor(max_workers=N).
Each worker forks the rayon thread pool — without explicit sizing, every
worker spawns num_cpus threads, leading to N × num_cpus contending
threads on a single node.
Set the per-worker rayon thread count via set_num_threads(n) in the
worker initialiser. Recommended sizing: n = num_cpus // num_workers.
Example: 16-core node with 8 workers → set_num_threads(2).
from concurrent.futures import ProcessPoolExecutor
import schicluster_rs
def worker_init():
schicluster_rs.set_num_threads(2)
schicluster_rs.patch_schicluster()
with ProcessPoolExecutor(max_workers=8, initializer=worker_init) as ex:
list(ex.map(impute_one_cell, cells))
Layout
rust-scHiCluster/
├── pyproject.toml maturin build config
├── README.md this file
├── LICENSE MIT
├── rust/
│ ├── Cargo.toml
│ └── src/lib.rs all algorithms (~500 LoC)
├── python/
│ └── schicluster_rs/__init__.py thin Python wrapper + monkey-patch
└── tests/
└── test_parity.py parity vs scipy on random sparse matrices
Algorithm notes
The hot loop is the iterative random-walk-with-restart, which is implemented as a Sparse-times-Dense matrix multiplication (SpMM) with rayon row-wise parallelism:
P(sparse, ~7 nnz per row after Gaussian smoothing) stays as CSR.Q(the iterate) is stored dense, since RWR diffuses it to ≥ 30 % density after 1–2 iterations anyway.- Each iteration:
Q' = (1−rp) · (P · Q) + rp · P. TheP · Qmatmul is computed row-wise; each output row is independent, so rayon splits row-chunks across cores. Within each row, the inner AXPY (accumulateP[i,k] · Q[k, :]for sparse k) vectorises cleanly.
Other steps (Gaussian convolution, SQRTVC normalize, triangle filter) are similarly multi-threaded over rows or chunks.
For users who can tolerate ≪1% deviation from the strict scipy result,
a band_factor parameter is available that runs the RWR with a banded
Q (only entries with |j − i| ≤ band_factor × output_dist_bins),
giving an additional ~4× speedup. Default is 0 (off, strict).
Citation
If you use this package, please cite the original scHiCluster paper:
Zhou, J., Ma, J., Chen, Y., Cheng, C., Bao, B., Peng, J., Sejnowski, T. J., Dixon, J. R. & Ecker, J. R. (2019). Robust single-cell Hi-C clustering by convolution- and random-walk-based imputation. PNAS, 116(28):14011-14018.
License
MIT.
Release files for schicluster-rs 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| schicluster_rs-0.1.1.tar.gz | 18.3 kB | Details |
Built distributions (wheels)
| File | Reset | |||
|---|---|---|---|---|
| schicluster_rs-0.1.1-cp39-abi3-win_amd64.whl | CPython 3.9 | abi3 | Windows x86-64 | Details |
| schicluster_rs-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ x86-64 | Details |
| schicluster_rs-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl | CPython 3.9 | abi3 | Linux glibc 2.17+ ARM64 | Details |
| schicluster_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl | CPython 3.9 | abi3 | macOS 11.0+ ARM64 | Details |
| schicluster_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl | CPython 3.9 | abi3 | macOS 10.12+ x86-64 | Details |
Total release size: 1.6 MB
Release files / schicluster_rs-0.1.1.tar.gz
| Download URL | schicluster_rs-0.1.1.tar.gz |
|---|---|
| Size | 18.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
df01487907afd40709b9c9347d6bbd46f657a6a90d5f4e008e3915bb6e956cfb
|
|
BLAKE2b-256 checksum How to use checksums |
bcfbccf6e61aa0e9885c6f5a2de54bd67db33f555f1841f49cb6f3b94d462a60
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 26, 2026.
Transparency logRelease files / schicluster_rs-0.1.1-cp39-abi3-win_amd64.whl
| Download URL | schicluster_rs-0.1.1-cp39-abi3-win_amd64.whl |
|---|---|
| Size | 222.7 kB |
| Tags | CPython 3.9 Windows x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7dd0c18aa680cd6a4069ad4aea9200b1de901cd3a019aedc187ac4581f276f9d
|
|
BLAKE2b-256 checksum How to use checksums |
7c81a08f3007d85e0a3da72e156453d007ab4bef1149d45ba1f23518401d9a76
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 26, 2026.
Transparency logRelease files / schicluster_rs-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
| Download URL | schicluster_rs-0.1.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl |
|---|---|
| Size | 356.9 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ x86-64 abi3 |
|
SHA-256 checksum How to use checksums |
7805db45b93373762c1988e1bc2fc65c0022f712733d70ba9fa5e3871d2d8d03
|
|
BLAKE2b-256 checksum How to use checksums |
d4d0cbe9db7ec7a04dcb2fad1398bac5167b3c4af2e3f0391a7ce82da5a5cfb7
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 26, 2026.
Transparency logRelease files / schicluster_rs-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
| Download URL | schicluster_rs-0.1.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl |
|---|---|
| Size | 357.0 kB |
| Tags | CPython 3.9 Linux glibc 2.17+ ARM64 abi3 |
|
SHA-256 checksum How to use checksums |
5cf4b163ddb5298a9d36766fb1e13d8f69327ba4de08dbf5ddb230d893b11bf3
|
|
BLAKE2b-256 checksum How to use checksums |
83203823a29fa5749a0981e84bb4eba01edb6c3518c9e507c57f9778e8001f78
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 26, 2026.
Transparency logRelease files / schicluster_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl
| Download URL | schicluster_rs-0.1.1-cp39-abi3-macosx_11_0_arm64.whl |
|---|---|
| Size | 316.6 kB |
| Tags | CPython 3.9 abi3 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
87225bbd82ac0bafcebd1e949db7e37557acc2d8feaeba3d9cc8deb84290ccf6
|
|
BLAKE2b-256 checksum How to use checksums |
be6d184ff1ab0136156416f46bb5dbdb6ea6f0203863171f6410867b73364cd0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 26, 2026.
Transparency logRelease files / schicluster_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl
| Download URL | schicluster_rs-0.1.1-cp39-abi3-macosx_10_12_x86_64.whl |
|---|---|
| Size | 322.9 kB |
| Tags | CPython 3.9 abi3 macOS 10.12+ x86-64 |
|
SHA-256 checksum How to use checksums |
4268ae05cd601aac6eca71ced7a816f0767ac8091628ffa346c8d6a8f519e127
|
|
BLAKE2b-256 checksum How to use checksums |
7c860095010e33a7a35e5515f94cb61567f99857bd5d3724c4467217c7e65dae
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
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 Apr 26, 2026.
Transparency log