Skip to content

v0.3.0

Choose a tag to compare

@p-gueguen p-gueguen released this 31 Mar 11:02
51def76

What's Changed

Bug Fixes

  • counts_MIN pixel filter now enforced (fixes #11): R spacexr calls restrict_counts() twice — the second call with gene_list_bulk was missing from rctd-py. Pixels with fewer than counts_MIN=10 counts 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.compile fails 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, plus RCTDConfig(compile=False) and --no-compile CLI flag for explicit control.

  • cuSOLVER batch-size crash fix: torch.linalg.eigh has 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_mask in result types (fixes #8, fixes #9): FullResult, DoubletResult, and MultiResult now include a pixel_mask field (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=10 is now enforced — result pixel counts will differ from v0.2.x (fewer pixels, matching R spacexr).
  • FullResult, DoubletResult, MultiResult gain a pixel_mask field (default None, backward-compatible for direct run_*_mode() callers).
  • RCTDConfig gains a compile field (default True).

Validation

  • 100/100 tests pass (Python 3.10-3.12)
  • Xenium Region 1: n_filtered=13,936 exact 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