v0.3.0
What's Changed
Bug Fixes
-
counts_MIN pixel filter now enforced (fixes #11): R spacexr calls
restrict_counts()twice — the second call withgene_list_bulkwas missing from rctd-py. Pixels with fewer thancounts_MIN=10counts in the DE gene set are now correctly removed. Validated: exact pixel count match with R spacexr on Xenium Region 1 (n_filtered=13,936). -
torch.compile fallback for environments without CUDA headers (fixes #10):
torch.compilefails at runtime on GPU nodes without CUDA development headers (cuda.h) because Triton attempts to compile CUDA code. Added lazy auto-detection with graceful fallback to eager mode, plusRCTDConfig(compile=False)and--no-compileCLI flag for explicit control. -
cuSOLVER batch-size crash fix:
torch.linalg.eighhas an undocumented batch-size limit in CUDA 12.8 (~27k-31k depending on K). Added_eigh_safe()that sub-batches at 25k, fixing crashes at--batch-size 50000.
New Features
pixel_maskin result types (fixes #8, fixes #9):FullResult,DoubletResult, andMultiResultnow include apixel_maskfield (boolean array matching the input AnnData shape). Maps results back to original barcodes:result = run_rctd(spatial, reference) weights_df = pd.DataFrame( result.weights, index=spatial.obs_names[result.pixel_mask], columns=result.cell_type_names, )
Improvements
-
Memory: sparse-aware reference profiles: Large references (370k+ cells) no longer require
.todense()during profile computation. Sparse mat-vec products keep memory usage proportional to non-zero entries. -
Numerical precision:
_longdouble_sum()uses numpy longdouble (80-bit) for bulk reductions, matching R's extended precision on x86-64. -
Tutorial notebook fixed: Marimo figures now render in static HTML export.
Breaking Changes
counts_MIN=10is now enforced — result pixel counts will differ from v0.2.x (fewer pixels, matching R spacexr).FullResult,DoubletResult,MultiResultgain apixel_maskfield (defaultNone, backward-compatible for directrun_*_mode()callers).RCTDConfiggains acompilefield (defaultTrue).
Validation
- 100/100 tests pass (Python 3.10-3.12)
- Xenium Region 1:
n_filtered=13,936exact match with R,dominant_type_agreement=0.9973,pixel_corr_median=1.0 - No runtime regression on tutorial or Xenium benchmarks
Full Changelog: v0.2.2...v0.3.0