Xenium
A Xenium Onboard Analysis output bundle (XOA 1 to 4): the cell x feature
counts, the table of cells with their centroids, and the clustering, UMAP
and PCA Xenium computed. Give the bundle folder; it is recognised by
experiment.xenium beside cell_feature_matrix.h5.
adata convert output-XETG00000__0001234__Region_1 -o region1.h5ad
adata convert xenium_bundle -o region1.h5ad --feature-type "Gene Expression"
| Xenium | AnnData |
|---|---|
cell_feature_matrix.h5 |
X, var, as a 10x HDF5 file is read: Gene Expression and the control probes and codewords, each a feature type |
cells.csv.gz: cell_id |
the obs names (the matrix’s barcodes) |
cells.csv.gz: x_centroid, y_centroid |
obsm["spatial"], [x, y] in microns |
cells.csv.gz: every other column (transcript_counts, cell_area, nucleus_area, segmentation_method, …) |
obs columns, typed as pandas reads them; text as a categorical when it repeats a value, as anndata writes it |
analysis/clustering/gene_expression_graphclust/clusters.csv |
obs["graphclust"], a categorical |
analysis/umap/gene_expression_2_components/projection.csv |
obsm["X_umap"] |
analysis/pca/gene_expression_10_components/projection.csv |
obsm["X_pca"] |
| the matrix’s run metadata | uns["cellranger"] |
Xenium ships analysis/ packed as analysis.tar.gz. When it has not been
unpacked, the three tables above are copied out of it, by name, into a
temporary folder beside the output, removed when the conversion ends. A cell an
analysis table lacks is left empty (no cluster, NaN), with a warning
giving the count.
The 10x HDF5 flags (--var-names, --make-unique,
--feature-type, --split-feature-types) apply. Cell boundaries,
transcripts and the morphology images are not read.
Differences from spatialdata-io
spatialdata-io’s xenium reader returns a SpatialData, whose table holds
the same cells and obsm["spatial"]. Its obs also has cell_id as a
column, which here is the obs names, and a region column naming the
SpatialData element the table annotates, which an AnnData on its own has
no use for. CI checks the import against 10x’s own recipe for scanpy:
read_10x_h5, the cell table reindexed to it, the analysis tables.
How it is read
The cell table can hold a million rows. It is matched to the matrix’s barcodes while it is scanned, and Xenium writes the two in the same order, so it is then written straight through, a block at a time. A table in another order is written in the matrix’s order through scratch space beside the output; cells the matrix lacks are left out, with a warning. A cell of the matrix with no row in the table is refused before anything is written.
A bundle with cells.parquet and no cells.csv.gz is refused: Parquet is
not read yet.