Skip to content

Repository files navigation

rctd-rust

CI

Installable CPU/Rayon acceleration for p-gueguen/rctd-py, a Python implementation of Robust Cell Type Decomposition (RCTD) for spatial transcriptomics. It accepts the same AnnData, Reference, RCTDConfig, and mode names as rctd-py.

rctd-rust is aimed at CPU execution. The validated path moves bulk fitting, Q-table spline construction, sigma selection, and the complete doublet fit into Rust, with Rayon parallelism around whole stages. It does not require a GPU.

Status: alpha. Version 0.2.0 pins rctd-py==0.3.7 because its integration follows that version's orchestration API. The bundled benchmark fixture is synthetic and the package should be validated on representative biological data before production use.

Results

On the included synthetic CPU doublet fixture (100 pixels, 200 genes, 5 cell types), the final implementation measured a stable 8.3–8.7x in-process speedup. Fresh-process measurements averaged about 9.7x and were noisier.

Correctness against the frozen Python output:

Check Result
Minimum per-spot Pearson, weights 0.999999999998
Maximum absolute weight difference 1.447e-6
Maximum doublet-weight difference 3.061e-8
Classification / selected types Identical

See REPORT.md for the benchmark method, ablations, and caveats.

Installation

Prebuilt wheel

Download the wheel for your operating system from the latest release, then install it with pip:

python -m pip install /path/to/rctd_rust-0.2.0-*.whl
rctd-rust info

Wheels use Python's stable ABI and support Python 3.10–3.13. Release automation builds Windows x86-64, Linux x86-64, and macOS x86-64 wheels. The wheel installs the tested rctd-py dependency automatically.

Install from GitHub source

Source installation works on Windows, Linux, and macOS and requires a stable Rust toolchain:

python -m pip install "rctd-rust @ git+https://github.com/LCGaoZzz/rctd-rust.git@v0.2.0"
rctd-rust info

For development:

git clone https://github.com/LCGaoZzz/rctd-rust.git
cd rctd-rust
python -m venv .venv
# Windows: .venv\Scripts\activate
# Linux/macOS: source .venv/bin/activate
python -m pip install --upgrade pip maturin
maturin develop --release
rctd-rust info

Quick start

The upstream workflow stays the same; import run_rctd from rctd_rust:

import anndata

from rctd import RCTDConfig, Reference
from rctd_rust import run_rctd

reference_adata = anndata.read_h5ad("reference.h5ad")
spatial = anndata.read_h5ad("spatial.h5ad")

reference = Reference(reference_adata, cell_type_col="cell_type")
config = RCTDConfig(device="cpu", compile=False)

result = run_rctd(
    spatial,
    reference,
    mode="doublet",
    config=config,
)

print(result.weights.shape)          # pixels x cell types
print(result.weights_doublet.shape)  # pixels x 2
print(result.cell_type_names)

The complete runnable version is in examples/quickstart.py:

python examples/quickstart.py reference.h5ad spatial.h5ad

Input requirements

  • Both inputs are AnnData objects with raw counts in .X.
  • Gene names are read from .var_names and must overlap between the inputs.
  • The reference needs a cell-type column in .obs; the default name is cell_type.
  • RCTD performs its normal UMI and cell-type-size filtering. For very small test data, lower UMI_min, UMI_min_sigma, cell_min, or min_UMI.

Modes

Mode Use case Native coverage in 0.2.0
doublet Sparse platforms; select one or two types per pixel Full Rust/Rayon fitting path
full Estimate all cell-type weights Rust preprocessing; upstream per-pixel solver
multi Select up to several types per pixel Rust preprocessing; upstream greedy solver

The return objects and fields are the upstream FullResult, DoubletResult, and MultiResult types. See the rctd-py documentation for the full parameter and result-field reference.

Deterministic spatial graph

Version 0.2.0 also exposes a lightweight NumPy API for radius-limited spatial graphs without importing Torch or AnnData:

from rctd_rust import radius_knn_graph_2d

indices, distances, counts = radius_knn_graph_2d(
    coordinates,       # float64, shape (cells, 2)
    global_id_ranks,   # int64 lexicographic ranks, shape (cells,)
    radius=15.0,
    max_neighbors=20,
)

The kernel uses a uniform 2D grid and Rayon, excludes equal cell identities, and sorts neighbors by distance then global-cell-ID rank. The bundled Xenium benchmark verifies exact edge hashes against the Omicos Python/cKDTree implementation at 10,000, 50,000, and 100,000 simulated cells.

Hierarchical cell types

Doublet mode supports the upstream class_df mapping:

from rctd import RCTDConfig

config = RCTDConfig(
    device="cpu",
    compile=False,
    class_df={
        "CD4_TH1": "T_cell",
        "CD4_TH2": "T_cell",
        "CD8": "T_cell",
        "B_naive": "B_cell",
    },
)

Verification and benchmark

Run the frozen end-to-end correctness gate:

python scripts/verify_fixture.py

It runs the included reference.h5ad and spatial.h5ad, then requires Pearson greater than 0.9999, maximum error below 1e-3, and identical classification labels. The first run may download the upstream Q matrices.

To reproduce the historical benchmark harness after installing the package:

python work/bench/fresh_runner.py combo_v5

To reproduce the Xenium graph benchmark against an Omicos Skill checkout:

python work/bench/spatial_graph_benchmark.py \
  --diagnostic /path/to/xenium-signal-integrity-pro/scripts/diagnostic.py

Threads and cache

Rayon uses its normal thread-pool sizing. Set RAYON_NUM_THREADS before Python starts to cap native threads:

RAYON_NUM_THREADS=8 python analysis.py

Set RCTD_RUST_SERIAL=1 to disable Rayon for debugging. The first run writes an uncompressed, C-contiguous Q-table cache to ~/.cache/rctd-rust. Override that location with RCTD_RUST_CACHE_DIR.

Repository layout

  • src/rctd_rust/: installable Python API and native adapter.
  • work/variants/rctd_rs/: Rust/PyO3/Rayon native source.
  • tests/: package and native-boundary tests.
  • scripts/verify_fixture.py: frozen end-to-end correctness gate.
  • work/bench/: optimization campaign benchmark harness.
  • work/rctd-py-src/rctd-py-main/: upstream snapshot used by the campaign.
  • reference.h5ad, spatial.h5ad: generated synthetic fixture.

Provenance and license

The bundled source snapshot originates from p-gueguen/rctd-py, revision be26f22adc2281bf034a56148af317658ee3b3d7. Upstream authorship and its full GPL-3.0-or-later license text are preserved under work/rctd-py-src/.

This derivative is distributed under GPL-3.0-or-later. It is an independent experimental accelerator and is not an official upstream release.

About

Validated CPU/Rayon Rust acceleration prototype for rctd-py

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages