Written and maintained by CASRAI Editorial Board
Last updated
SpatialData is an open-source, modular Python data framework developed within the scverse consortium to standardize the storage, alignment, and programmatic manipulation of multi-modal spatial omics datasets. Described by Marconato et al. in Nature Methods (2025; DOI: 10.1038/s41592-024-02212-x), the library establishes a unified, language-independent representation for heterogeneous spatial biology data—spanning spatial transcriptomics, multiplexed antibody imaging, and deep histology.
High-plex tissue profiling technologies generate complex mixtures of high-resolution raster images, coordinate point clouds of individual RNA molecules, geometric cell boundary segmentations, and tabular gene expression matrices. Historically, computational biologists were forced to build bespoke ad-hoc data wrangling pipelines across disparate formats, risking silent coordinate misalignment and computational memory exhaustion. SpatialData resolves this bottleneck by integrating standard Scientific Python data structures (xarray, Dask, GeoPandas, and AnnData) under the Open Microscopy Environment Next-Generation File Formats (OME-NGFF) Zarr specification, enabling lazy evaluation and out-of-core processing of multi-gigabyte tissue specimens aligned with rigorous FAIR data principles.
What it is used for in research
In modern biomedical and computational biology research, SpatialData serves as the central data infrastructure for ingesting, querying, and sharing high-dimensional spatial assays. Rather than treating an imaging assay and a single-cell sequencing assay as separate experimental outputs, SpatialData packages all analytical layers of a biological specimen into a single coordinated object container. Key research applications include:
- Multi-Modal Data Unification: Encapsulating five fundamental biological data modalities within a single dataset:
- Images: Multi-channel, multi-scale pixel rasters (e.g., brightfield H&E, multi-cycle immunofluorescence, imaging mass cytometry) backed by
xarray.DataArrayor pyramidalxarray.DataTree. - Labels: Discrete 2D or 3D integer segmentation masks denoting individual cell, nuclear, or histological compartment boundaries.
- Points: Subcellular coordinate tables recording single-molecule transcripts (such as 10x Xenium or Vizgen MERSCOPE reads) managed via lazy
dask.dataframe.DataFrame. - Shapes: Vector polygon boundaries, multipolygons, or circular capture locations (e.g., 10x Visium spots) managed via GeoPandas
GeoDataFrame. - Tables: Count matrices and metadata feature annotations managed as
anndata.AnnData, explicitly linked to segmentation labels or vector shapes through standardized region attributes.
- Images: Multi-channel, multi-scale pixel rasters (e.g., brightfield H&E, multi-cycle immunofluorescence, imaging mass cytometry) backed by
- Cross-Modal Coordinate Alignment: Connecting disparate image coordinate spaces (camera pixels), physical stage positions (micrometers), and reference tissue atlases through an explicit coordinate transformation graph.
- Subsetting and Region-of-Interest (ROI) Extraction: Cropping complex multi-modal tissue sections using bounding boxes or arbitrary polygonal masks, with automated synchronization of associated cellular expression matrices.
- FAIR Data Sharing and Long-Term Archiving: Serializing multi-omics experiments to OME-NGFF Zarr directory stores for publication deposits and reproducible re-analysis, advancing standards for making datasets FAIR.
Install or access (official source only)
SpatialData is distributed through the Python Package Index (PyPI) and Conda-Forge under the open-source BSD 3-Clause License. It requires Python 3.9 or newer. To ensure full environment stability and avoid dependency conflicts across computational biology workflows, install the framework inside an isolated virtual environment or consult best practices for sharing a reproducible conda environment.
Install the core package using pip:
pip install spatialdata
To install SpatialData with recommended companion dependencies (including optimized spatial query routines and plotting utilities), install the extra feature bundle:
pip install "spatialdata[extra]"
Alternatively, install via the conda-forge channel using Conda or Mamba:
conda install -c conda-forge spatialdata
For research labs processing raw instrument outputs from commercial spatial biology platforms, install the official companion ingestion package spatialdata-io:
pip install spatialdata-io
For data visualization, the scverse ecosystem provides two official rendering packages:
spatialdata-plot: Static visualization engine integrated with Matplotlib (pip install spatialdata-plot).napari-spatialdata: Interactive multi-dimensional visualization plugin for the Napari viewer (pip install napari-spatialdata).
Step-by-step task
The following worked research workflow demonstrates how to load an OME-Zarr spatial dataset, inspect its multi-modal elements, verify coordinate transformations, execute a spatial bounding-box crop with automated table filtering, and serialize the processed subset for archival storage.
-
Import the framework and load the dataset from disk:
Read an existing OME-Zarr directory into a lazy in-memory
SpatialDataobject:import spatialdata as sd from spatialdata import bounding_box_query from spatialdata.transformations import get_transformation, set_transformation, Scale # Load an OME-Zarr directory containing histology and transcriptomic layers sdata = sd.read_zarr("sample_tissue_section.zarr") print(sdata) -
Inspect contained elements and coordinate systems:
Verify the names and types of available spatial elements and check their coordinate system mappings:
# Query available element groups print("Images:", list(sdata.images.keys())) print("Labels:", list(sdata.labels.keys())) print("Points:", list(sdata.points.keys())) print("Shapes:", list(sdata.shapes.keys())) print("Tables:", list(sdata.tables.keys())) # Inspect the coordinate systems defined on the main histology image image_name = list(sdata.images.keys())[0] image_element = sdata[image_name] print("Coordinate systems:", sdata.coordinate_systems) -
Define and assign a physical coordinate transformation:
If an image raster lacks calibrated physical coordinates, apply a scaling transform to map pixel coordinates to physical micrometers:
# Map pixel grid (0.2125 um/pixel) to a physical coordinate system named 'microns' pixel_to_microns = Scale([0.2125, 0.2125], axes=("y", "x")) set_transformation(image_element, pixel_to_microns, to_coordinate_system="microns") # Confirm the transformation was stored current_transform = get_transformation(image_element, to_coordinate_system="microns") print("Assigned transform:", current_transform) -
Execute a spatial bounding-box query to crop a region of interest:
Perform a spatial subset across all registered layers. By default,
filter_table=Trueautomatically subsets the associatedAnnDatatable rows to keep only the segmented cells located within the bounding box:# Define bounding box boundaries in the target coordinate system (microns) cropped_sdata = bounding_box_query( sdata, axes=("y", "x"), min_coordinate=[1500, 2000], max_coordinate=[3500, 4000], target_coordinate_system="microns", filter_table=True ) # Verify that the cropped container retains synchronized elements print("Cropped container summary:") print(cropped_sdata) -
Serialize and persist the cropped dataset:
Write the resulting cropped dataset to a clean OME-Zarr directory for reproducible downstream analysis or cloud deposit:
# Persist the processed SpatialData object to disk cropped_sdata.write("processed_roi_subset.zarr")
Output and how to read it
When you print or inspect a SpatialData container in Python, the output displays a concise diagnostic summary structured across element modalities, dimensions, and coordinate frameworks. Below is an example of the standard printed representation:
SpatialData object
├── Images
│ └── 'he_microscopy': MultiscaleSpatialImage[cyx] (3, 8400, 7200), (3, 4200, 3600), (3, 2100, 1800)
├── Labels
│ └── 'cell_segmentations': SpatialImage[yx] (8400, 7200)
├── Points
│ └── 'transcripts': Dask DataFrame (4 columns: x, y, gene, quality_score; 12,450,210 rows)
├── Shapes
│ └── 'cell_boundaries': GeoDataFrame (geometry: Polygon; 42,150 rows)
├── Tables
│ └── 'table': AnnData (42,150 observations x 18,500 variables)
└── Coordinate systems
├── 'global' (elements: 'he_microscopy', 'cell_segmentations')
└── 'microns' (elements: 'he_microscopy', 'cell_segmentations', 'transcripts', 'cell_boundaries')
Understanding each component of this output ensures data integrity throughout downstream analysis:
- Multiscale Pyramids: In the
Imagesblock, multiscale representations display multiple downscaled pyramid levels. This structure allows interactive tools like Napari to stream downsampled views dynamically without loading full gigabyte-scale rasters into memory. - Points Partitioning: The
Pointsblock displays coordinates backed by Dask DataFrames. Because operations remain lazy, the 12+ million transcript records are not evaluated in RAM until an explicit spatial query or compute call is triggered. - Table Linking Metadata: In the
Tablesblock, theAnnDataobject contains critical structured metadata stored undersdata.tables['table'].uns['spatialdata_attrs']. This dictionary specifies:region: Names the spatial element annotated by the table (e.g.,'cell_boundaries').region_key: The observation column identifying which region a cell belongs to.instance_key: The observation column containing integer IDs that match the index of the shapes or pixel values of the labels.
- Coordinate Systems: The bottom block lists the active coordinate systems and enumerates every spatial element currently mapped to them. Queries and cross-modal overlays can only be performed across elements mapped to a shared target system.
Troubleshooting
Operational troubleshooting in SpatialData centers on lazy execution bottlenecks, coordinate transformations, and table synchronization. The table below lists standard failure modes and validated solutions:
| Issue | Diagnostic Symptom | Root Cause | Corrective Action |
|---|---|---|---|
| Kernel Crash or OOM | Process terminates during points or raster manipulation without a Python traceback. | Accidentally executing .compute() on massive Dask point tables or calling .values on an uncropped full-resolution xarray image. |
Preserve lazy evaluation. Always perform spatial cropping via bounding_box_query() or polygon_query() before requesting in-memory numpy arrays or pandas DataFrames. |
| CoordinateSystemError | KeyError or CoordinateSystemError: Coordinate system 'microns' not found for element. |
Attempting a spatial query or cross-layer overlay in a coordinate system to which not all involved elements have been mapped. | Verify transformations using get_transformation(element). Call set_transformation(element, transform, to_coordinate_system="...") to ensure all target elements share the query coordinate system. |
| Desynchronized AnnData Table | Cropped SpatialData object retains all original observations in sdata.tables['table'] despite spatial filtering. |
Table was constructed without valid spatialdata_attrs in table.uns, or filter_table=False was passed to the query. |
Ensure table.uns['spatialdata_attrs'] correctly specifies region, region_key, and instance_key matching the filtered shape or label element. Verify filter_table=True during queries. |
| Zarr Write Permission Error | ContainsGroupError or FileExistsError during sdata.write(). |
SpatialData protects existing data stores from inadvertent clobbering by refusing to overwrite on-disk Zarr groups by default. | Pass overwrite=True to sdata.write("output.zarr", overwrite=True) or output to a distinct file path. For large datasets, ensure no other background processes or file locks are open on the Zarr store. |
Free alternatives
SpatialData is designed specifically to overcome the multi-modal limitations of earlier computational tools. When choosing software for research, computational biologists evaluate several free, open-source alternatives across data models, languages, and scalability:
| Software | Primary Language | Underlying Storage Model | Supported Modalities | Optimal Research Use Case |
|---|---|---|---|---|
| SpatialData | Python (scverse) | OME-NGFF Zarr, Parquet, xarray, Dask, AnnData | Images, Labels, Points, Shapes, Tables | Large-scale multi-modal spatial omics, out-of-core compute, OME-Zarr FAIR data sharing, and cross-platform alignment. |
| Squidpy (standalone) | Python (scverse) | In-memory AnnData (with adata.obsm['spatial']) |
Capture spot coordinates, segmented cell centroids, feature tables | Neighborhood graph analysis, spatial autocorrelation (Moran’s I), and spatial clustering on standard Visium or single-cell spot arrays. |
| SpatialExperiment | R (Bioconductor) | S4 class extending SingleCellExperiment | Spot coordinates, image metadata, feature tables | Standardized R/Bioconductor statistical pipelines, differential expression, and spot-level spatial transcriptomics workflows. |
| Giotto Suite | R (with Python backend) | S4 Giotto object, cellular polygon geometries | Subcellular transcripts, cell polygons, staining images, count tables | End-to-end spatial data exploration, cell-cell communication modeling, and multi-scale spatial analysis within the R ecosystem. |
| Seurat (v5) | R | S4 Seurat object (FOV / assay structure) | Images, spot centroids, single-molecule coordinates, expression matrices | Integrated single-cell RNA-seq and spatial transcriptomics analysis within existing Seurat laboratory workflows. |
While standalone single-cell tools such as Squidpy or SpatialExperiment excel at statistical testing on cell centroids, SpatialData provides the structural foundation required when an experiment combines raw microscopy rasters, polygonal boundaries, and millions of sub-cellular point coordinates. For broader comparisons of computational infrastructures, review the what is bioinformatics overview and the FAIR research software checklist.
FAQ
- Which spatial omics platforms are natively supported by SpatialData?
- Through its companion package
spatialdata-io, SpatialData supports direct automated ingestion of raw outputs from 10x Genomics Visium, 10x Genomics Visium HD, 10x Genomics Xenium, Vizgen MERSCOPE, NanoString/Bruker CosMx Spatial Molecular Imager, Curio Seeker, Akoya PhenoCycler (CODEX), and Steinbock multiplexed imaging pipelines. - How does SpatialData differ from standard AnnData?
- Standard
AnnDatais designed primarily for 2D observation-by-variable matrices (e.g., cell-by-gene counts) and typically stores spatial coordinates as static 2D arrays inobsm['spatial']. It cannot natively represent pyramidal multi-channel images, polygon segmentation vectors, or millions of subcellular transcript coordinates without memory exhaustion. SpatialData incorporates AnnData as itsTableselement while managing rasters, shapes, and points through specialized out-of-core libraries (xarray, GeoPandas, and Dask). - What file format does SpatialData write to disk?
- SpatialData serializes datasets to disk using the Open Microscopy Environment Next-Generation File Formats (OME-NGFF v0.4) specification built upon Zarr storage hierarchies. Vector shapes and point clouds are stored using Apache Parquet and GeoParquet conventions within the Zarr store, ensuring vendor-neutrality, cloud-readiness, and long-term digital preservation.
- Can SpatialData objects be used from the R programming language?
- Yes. The scverse ecosystem provides
SpatialDatain R (available via Bioconductor and r-universe), which uses thebasiliskenvironment manager or direct reticulate bindings to read, manipulate, and convert SpatialData OME-Zarr stores into native BioconductorSpatialExperimentobjects. - How does SpatialData handle coordinate alignment across serial tissue sections?
- SpatialData uses an explicit transformation graph. Each individual tissue slice retains its native acquisition coordinate system (e.g., pixel indices or stage coordinates). Researchers can compute rigid or affine transformation matrices (using landmark registration or automated image registration algorithms) and assign them via
set_transformation()to a shared common coordinate framework (e.g., ‘atlas_space’) without rewriting or interpolating raw data on disk.
Sources
- Marconato, L., Palla, G., Yamauchi, K.A., Virshup, I., et al. (2025). SpatialData: an open and universal data framework for spatial omics. Nature Methods, 22:58–62. DOI: 10.1038/s41592-024-02212-x. Read 2026-11-07.
- scverse Consortium. SpatialData Official Documentation: User Guide, Data Model, and API Reference. https://spatialdata.scverse.org/. Read 2026-11-07.
- scverse Consortium. SpatialData GitHub Repository and Architecture Specification (BSD 3-Clause License). https://github.com/scverse/spatialdata. Read 2026-11-07.
- scverse Consortium. spatialdata-io Ingestion Library Documentation. https://github.com/scverse/spatialdata-io. Read 2026-11-07.







