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.7because 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.
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.
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 infoWheels 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.
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 infoFor 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 infoThe 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- Both inputs are
AnnDataobjects with raw counts in.X. - Gene names are read from
.var_namesand must overlap between the inputs. - The reference needs a cell-type column in
.obs; the default name iscell_type. - RCTD performs its normal UMI and cell-type-size filtering. For very small
test data, lower
UMI_min,UMI_min_sigma,cell_min, ormin_UMI.
| 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.
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.
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",
},
)Run the frozen end-to-end correctness gate:
python scripts/verify_fixture.pyIt 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_v5To 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.pyRayon uses its normal thread-pool sizing. Set RAYON_NUM_THREADS before Python
starts to cap native threads:
RAYON_NUM_THREADS=8 python analysis.pySet 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.
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.
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.