Skip to content

Read pre-1.3.0 / CSV-only Xenium bundles - #427

Open
timtreis wants to merge 1 commit into
mainfrom
fix/xenium-pre130-csv
Open

timtreis wants to merge 1 commit into
mainfrom
fix/xenium-pre130-csv

Conversation

@timtreis

@timtreis timtreis commented Oct 5, 2026

Copy link
Copy Markdown
Member

GEO Xenium deposits are commonly stripped to the flat outputs: no cells.zarr.zip, no parquet, and the counts matrix as MatrixMarket instead of cell_feature_matrix.h5. xenium() opened cells.zarr.zip and read the parquet unconditionally, so these raised FileNotFoundError before any fallback could run.

When those are absent, read the equivalents:

  • table metadata, cell/nucleus boundaries, transcripts ← .csv[.gz] (columns identical to the parquet)
  • raster cell/nucleus labels ← rasterized boundary polygons; keyed by integer cell_id, or by label_index from the boundary CSVs' label_id column for hex-id v2/v3 bundles (multinucleate nuclei included)
  • counts matrix ← cell_feature_matrix/ MatrixMarket dir or cell_feature_matrix.tar.gz when .h5 is missing

The zarr path is gated on cells.zarr.zip existing, not on the XOA version — hex-id ≥1.3.0 runs are deposited without it.

GEO examples this targets:

Tests: two committed CSV-only fixtures (10x Mouse Brain v1.0.2, integer id; Xenium Prime v3, hex id + label_id). Also checked against the full 10x v1.0.2 bundle (reconstructed label id-sets match the zarr masks, 36,602 cells) and a real GEO deposit (GSE283843, 13,178 cells).

Note: GEO strips experiment.xenium; a reconstructed manifest must carry pixel_size (the reader needs it for the micron↔pixel scale and does not guess it).

@codecov-commenter

codecov-commenter commented Oct 5, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.10345% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.57%. Comparing base (261578f) to head (642f014).

Files with missing lines Patch % Lines
src/spatialdata_io/readers/xenium.py 92.72% 8 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #427      +/-   ##
==========================================
+ Coverage   65.79%   66.57%   +0.77%     
==========================================
  Files          26       26              
  Lines        3263     3339      +76     
==========================================
+ Hits         2147     2223      +76     
  Misses       1116     1116              
Files with missing lines Coverage Δ
src/spatialdata_io/_constants/_constants.py 100.00% <100.00%> (ø)
src/spatialdata_io/readers/xenium.py 78.46% <92.72%> (+3.64%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@timtreis
timtreis force-pushed the fix/xenium-pre130-csv branch from b741f27 to 8150719 Compare October 5, 2026 22:05
XOA < 1.3.0 exports, and GEO deposits reduced to the CSV outputs, ship no
parquet and no cells.zarr.zip. xenium() opened cells.zarr.zip (via
_XeniumCells.open) and read the parquet files unconditionally, so it raised
FileNotFoundError on these bundles before any CSV-based path could run.

When cells.zarr.zip and the parquet files are absent:
- read the table metadata, cell/nucleus boundaries, and transcripts from the
  .csv[.gz] outputs (columns identical to the parquet ones);
- reconstruct the raster cell/nucleus labels by filling each boundary polygon
  with its integer label into a uint32 raster (as the zarr masks are) -- keyed
  by cell_id for pre-1.3.0 bundles, or by the label_index recovered from the
  boundary CSVs' label_id column for v2/v3 (hex cell_id, multinucleate nuclei
  supported). The table's cell_labels column and the raster share these exact
  values, honoring labels_models_kwargs (chunking/multiscale);
- read the cell feature matrix from a cell_feature_matrix/ MatrixMarket
  directory or cell_feature_matrix.tar.gz when cell_feature_matrix.h5 is
  missing.

The zarr path is gated on cells.zarr.zip existing, not on the XOA version.
Mapping the table to cell_labels degrades gracefully (warn, keep circles) when
a cell lacks a boundary, rather than raising.

Add committed CSV-only fixtures -- 30 cells of the 10x Mouse Brain v1.0.2
dataset (integer ids) and 12 cells of the Xenium Prime Mouse Brain v3 dataset
(hex ids + label_id) -- with tests asserting the reconstructed labels match the
table's cell_labels, plus the circles, uncompressed-.csv, and mtx variants.
@timtreis
timtreis force-pushed the fix/xenium-pre130-csv branch from 8150719 to 642f014 Compare October 5, 2026 22:28
@timtreis
timtreis marked this pull request as ready for review October 5, 2026 22:29
@timtreis
timtreis requested a review from LucaMarconato October 5, 2026 22:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants