Convert data from InSituPy into SpatialData#

Setup and Imports#

# Enable autoreload for development
%load_ext autoreload
%autoreload 2

Make sure SpatialData is installed#

If it is not installed yet, install it with:

pip install spatialdata[extra]

Make sure the version is >=0.7.2. For more information on the installation of SpatialData see here.

from pathlib import Path

from insitupy import InSituData, InSituExperiment, CACHE
from insitupy.spatialdata import convert_to_spatialdata

Load InSituPy Data#

First, let’s load some example data. We’ll demonstrate conversion with both:

  • InSituData: A single spatial sample

  • InSituExperiment: A collection of multiple samples

Loading a Single Sample (InSituData)#

# Load a single InSituData object
data_dir = Path(CACHE / "out/demo_insitupy_project")
xd = InSituData.read(data_dir)
xd.load_all()
# Display the InSituData object
xd
InSituData
Method:		Xenium
Slide ID:	0001879
Sample ID:	Replicate 1
Path:		C:\Users\ge37voy\.cache\InSituPy\out\demo_insitupy_project

    ➤ images
       'CD20':     (25778, 35416)
       'HE':       (25778, 35416, 3)
       'HER2':     (25778, 35416)
       'nuclei':   (25778, 35416)
    ➤ cells
       MultiCellData with main layer 'main'
           table
               AnnData object with n_obs × n_vars = 156447 × 297
               obs: 'transcript_counts', 'control_probe_counts', 'control_codeword_counts', 'total_counts', 'cell_area', 'nucleus_area', 'n_genes_by_counts', 'n_genes', 'leiden', 'cell_type_dc_sub_final', 'cell_type_publ'
               var: 'gene_ids', 'feature_types', 'genome', 'n_cells_by_counts', 'mean_counts', 'pct_dropout_by_counts', 'total_counts', 'n_cells'
               uns: 'cell_type_dc_sub_final_colors', 'cell_type_publ_colors', 'leiden', 'leiden_colors', 'log1p', 'neighbors', 'pca', 'umap'
               obsm: 'X_pca', 'X_umap', 'annotations', 'regions', 'spatial'
               varm: 'PCs'
               layers: 'counts', 'norm_counts'
               obsp: 'connectivities', 'distances'
           boundaries
               BoundariesData object with 2 entries:
                   cells
                   nuclei annotations
       Demo:	28 annotations, 2 classes ('Stroma', 'Tumor cells')
       demo2:	5 annotations, 3 classes ('Negative', 'Other', 'Positive')
       demo3:	7 annotations, 5 classes ('Immune cells', 'Necrosis', 'Stroma', 'Tumor', 'unclassified')
       Janesick:	18 annotations, 3 classes ('DCIS #1', 'DCIS #2', 'Invasive')
       Katja:	18 annotations, 4 classes ('DCIS', 'DCIS intermediate', 'DCIS with stromal reaction', 'Invasive')
       TestKey:	9 annotations, 2 classes ('TestClass', 'points')
    ➤ regions
       Demo:	3 regions, 3 classes ('Region 1', 'Region 2', 'Region 3')
       demo_regions:	3 regions, 3 classes ('Region1', 'Region2', 'Region3')
       Katja:	4 regions, 4 classes ('Region 1', 'Region 2', 'Region 3', 'Region 4')
       TMA:	6 regions, 6 classes ('A-1', 'A-2', 'A-3', 'B-1', 'B-2', 'B-3')
    ➤ transcripts
       DataFrame with shape <dask_expr.expr.Scalar: expr=ReadParquetFSSpec(ebf4dc6).size() // 8, dtype=int64> x 8

Create dataset with multiple samples (InSituExperiment)#

Note on Transcripts: Due to dependency conflicts between spatialdata and dask-geopandas, transcript cropping with dask DataFrames becomes very inefficient when spatialdata is installed. The dask-geopandas library is used for efficient spatial filtering of large transcript datasets, but it cannot be used alongside spatialdata.

To avoid performance issues when creating an InSituExperiment from regions (which involves cropping), we delete the transcripts beforehand.

Update: This issue may be resolved in an upcoming version of spatialdata. The dask version has been unpinned in PR #1006, which should allow dask-geopandas to be installed alongside spatialdata in a future release.

del xd.transcripts
exp = InSituExperiment.from_regions(
    data=xd,
    region_key="TMA"  # Column in annotations containing region IDs
)
# Display the experiment
exp
InSituExperiment (insitupy mode) with 6 samples:
           uid  CITAR slide_id    sample_id region_key region_name
0     92dc76ed  ++-++  0001879  Replicate 1        TMA         A-1
1     c9d5337d  ++-++  0001879  Replicate 1        TMA         A-2
2     77d55bd5  ++-++  0001879  Replicate 1        TMA         A-3
3     fda64ed4  ++-++  0001879  Replicate 1        TMA         B-1
4     9b82bec1  ++-++  0001879  Replicate 1        TMA         B-2
5     70c2bfd8  ++-++  0001879  Replicate 1        TMA         B-3

Convert to SpatialData#

The convert_to_spatialdata() function handles the conversion of all data modalities into SpatialData elements.

Element naming convention#

InSituPy uses a structured naming convention when converting to SpatialData:

Single Sample (InSituData):

MODALITY.key.subkey

Examples:

  • IMAGES.CD20 - CD20 staining image

  • CELLS.main.matrix - Main cell expression matrix

  • CELLS.main.boundaries.cells - Cell boundary masks

  • TRANSCRIPTS - Transcript point data

  • ANNOTATIONS.Demo - Annotation shapes

Multiple Samples (InSituExperiment):

SAMPLE.UID.MODALITY.key.subkey

When converting an InSituExperiment, each element is prefixed with the sample identifier to distinguish between samples:

Examples:

  • SAMPLE.1f1bcf1f.IMAGES.CD20 - CD20 image from Sample1

  • SAMPLE.1f1bcf1f.CELLS.main.matrix - Cell matrix from Sample1

  • SAMPLE.1f1bcf1f.IMAGES.CD20 - CD20 image from Sample2

  • SAMPLE.1f1bcf1f.TRANSCRIPTS - Transcripts from Sample2

3.1 Convert individual sample#

# Convert InSituData to SpatialData
sdata = convert_to_spatialdata(xd)
2026-02-24 13:46:56 | [INFO] No case-insensitive conflicts found.
# Display the SpatialData object
sdata
SpatialData object
├── Images
│     ├── 'IMAGES.CD20': DataTree[cyx] (1, 25778, 35416), (1, 12889, 17708), (1, 6444, 8854), (1, 3222, 4427), (1, 1611, 2213), (1, 805, 1106)
│     ├── 'IMAGES.HE': DataTree[cyx] (3, 25778, 35416), (3, 12889, 17708), (3, 6444, 8854), (3, 3222, 4427), (3, 1611, 2213), (3, 805, 1106)
│     ├── 'IMAGES.HER2': DataTree[cyx] (1, 25778, 35416), (1, 12889, 17708), (1, 6444, 8854), (1, 3222, 4427), (1, 1611, 2213), (1, 805, 1106)
│     └── 'IMAGES.nuclei': DataTree[cyx] (1, 25778, 35416), (1, 12889, 17708), (1, 6444, 8854), (1, 3222, 4427), (1, 1611, 2213), (1, 805, 1106)
├── Labels
│     ├── 'CELLS.main.boundaries.cells': DataTree[yx] (25778, 35416), (12889, 17708), (6444, 8854), (3222, 4427), (1611, 2213), (805, 1106)
│     └── 'CELLS.main.boundaries.nuclei': DataTree[yx] (25778, 35416), (12889, 17708), (6444, 8854), (3222, 4427), (1611, 2213), (805, 1106)
├── Shapes
│     ├── 'ANNOTATIONS.Demo': GeoDataFrame shape: (28, 6) (2D shapes)
│     ├── 'ANNOTATIONS.Janesick': GeoDataFrame shape: (18, 6) (2D shapes)
│     ├── 'ANNOTATIONS.Katja': GeoDataFrame shape: (18, 6) (2D shapes)
│     ├── 'ANNOTATIONS.TestKey': GeoDataFrame shape: (9, 6) (2D shapes)
│     ├── 'ANNOTATIONS.demo2': GeoDataFrame shape: (5, 6) (2D shapes)
│     ├── 'ANNOTATIONS.demo3': GeoDataFrame shape: (7, 6) (2D shapes)
│     ├── 'CELLS.main.circles': GeoDataFrame shape: (156447, 2) (2D shapes)
│     ├── 'CELLS.main.circles_sized': GeoDataFrame shape: (156447, 2) (2D shapes)
│     ├── 'REGIONS.Demo': GeoDataFrame shape: (3, 6) (2D shapes)
│     ├── 'REGIONS.Katja': GeoDataFrame shape: (4, 6) (2D shapes)
│     ├── 'REGIONS.TMA': GeoDataFrame shape: (6, 7) (2D shapes)
│     └── 'REGIONS.demo_regions': GeoDataFrame shape: (3, 6) (2D shapes)
└── Tables
      └── 'CELLS.main.table': AnnData (156447, 297)
with coordinate systems:
    ▸ 'global', with elements:
        IMAGES.CD20 (Images), IMAGES.HE (Images), IMAGES.HER2 (Images), IMAGES.nuclei (Images), CELLS.main.boundaries.cells (Labels), CELLS.main.boundaries.nuclei (Labels), ANNOTATIONS.Demo (Shapes), ANNOTATIONS.Janesick (Shapes), ANNOTATIONS.Katja (Shapes), ANNOTATIONS.TestKey (Shapes), ANNOTATIONS.demo2 (Shapes), ANNOTATIONS.demo3 (Shapes), CELLS.main.circles (Shapes), CELLS.main.circles_sized (Shapes), REGIONS.Demo (Shapes), REGIONS.Katja (Shapes), REGIONS.TMA (Shapes), REGIONS.demo_regions (Shapes)

3.2 Convert Experiment (Multiple Samples)#

# Convert InSituExperiment to SpatialData
sdexp = convert_to_spatialdata(exp)
2026-02-24 13:47:11 | [INFO] No case-insensitive conflicts found.
# Display the experiment SpatialData
sdexp
SpatialData object
├── Images
│     ├── 'SAMPLE.9b82bec1..IMAGES.CD20': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.9b82bec1..IMAGES.HE': DataTree[cyx] (3, 4706, 4706), (3, 2353, 2353), (3, 1176, 1176), (3, 588, 588), (3, 294, 294), (3, 147, 147)
│     ├── 'SAMPLE.9b82bec1..IMAGES.HER2': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.9b82bec1..IMAGES.nuclei': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.70c2bfd8..IMAGES.CD20': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.70c2bfd8..IMAGES.HE': DataTree[cyx] (3, 4706, 4706), (3, 2353, 2353), (3, 1176, 1176), (3, 588, 588), (3, 294, 294), (3, 147, 147)
│     ├── 'SAMPLE.70c2bfd8..IMAGES.HER2': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.70c2bfd8..IMAGES.nuclei': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.77d55bd5..IMAGES.CD20': DataTree[cyx] (1, 4706, 4705), (1, 2353, 2352), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.77d55bd5..IMAGES.HE': DataTree[cyx] (3, 4706, 4705), (3, 2353, 2352), (3, 1176, 1176), (3, 588, 588), (3, 294, 294), (3, 147, 147)
│     ├── 'SAMPLE.77d55bd5..IMAGES.HER2': DataTree[cyx] (1, 4706, 4705), (1, 2353, 2352), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.77d55bd5..IMAGES.nuclei': DataTree[cyx] (1, 4706, 4705), (1, 2353, 2352), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.92dc76ed..IMAGES.CD20': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.92dc76ed..IMAGES.HE': DataTree[cyx] (3, 4706, 4706), (3, 2353, 2353), (3, 1176, 1176), (3, 588, 588), (3, 294, 294), (3, 147, 147)
│     ├── 'SAMPLE.92dc76ed..IMAGES.HER2': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.92dc76ed..IMAGES.nuclei': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.c9d5337d..IMAGES.CD20': DataTree[cyx] (1, 4706, 4705), (1, 2353, 2352), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.c9d5337d..IMAGES.HE': DataTree[cyx] (3, 4706, 4705), (3, 2353, 2352), (3, 1176, 1176), (3, 588, 588), (3, 294, 294), (3, 147, 147)
│     ├── 'SAMPLE.c9d5337d..IMAGES.HER2': DataTree[cyx] (1, 4706, 4705), (1, 2353, 2352), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.c9d5337d..IMAGES.nuclei': DataTree[cyx] (1, 4706, 4705), (1, 2353, 2352), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.fda64ed4..IMAGES.CD20': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     ├── 'SAMPLE.fda64ed4..IMAGES.HE': DataTree[cyx] (3, 4706, 4706), (3, 2353, 2353), (3, 1176, 1176), (3, 588, 588), (3, 294, 294), (3, 147, 147)
│     ├── 'SAMPLE.fda64ed4..IMAGES.HER2': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
│     └── 'SAMPLE.fda64ed4..IMAGES.nuclei': DataTree[cyx] (1, 4706, 4706), (1, 2353, 2353), (1, 1176, 1176), (1, 588, 588), (1, 294, 294), (1, 147, 147)
├── Labels
│     ├── 'SAMPLE.9b82bec1..CELLS.main.boundaries.cells': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.9b82bec1..CELLS.main.boundaries.nuclei': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.70c2bfd8..CELLS.main.boundaries.cells': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.70c2bfd8..CELLS.main.boundaries.nuclei': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.77d55bd5..CELLS.main.boundaries.cells': DataTree[yx] (4706, 4705), (2353, 2352), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.77d55bd5..CELLS.main.boundaries.nuclei': DataTree[yx] (4706, 4705), (2353, 2352), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.92dc76ed..CELLS.main.boundaries.cells': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.92dc76ed..CELLS.main.boundaries.nuclei': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.c9d5337d..CELLS.main.boundaries.cells': DataTree[yx] (4706, 4705), (2353, 2352), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.c9d5337d..CELLS.main.boundaries.nuclei': DataTree[yx] (4706, 4705), (2353, 2352), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     ├── 'SAMPLE.fda64ed4..CELLS.main.boundaries.cells': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
│     └── 'SAMPLE.fda64ed4..CELLS.main.boundaries.nuclei': DataTree[yx] (4706, 4706), (2353, 2353), (1176, 1176), (588, 588), (294, 294), (147, 147)
├── Shapes
│     ├── 'SAMPLE.9b82bec1..ANNOTATIONS.Demo': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..ANNOTATIONS.Janesick': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..ANNOTATIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..ANNOTATIONS.TestKey': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..ANNOTATIONS.demo2': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..CELLS.main.circles': GeoDataFrame shape: (2301, 2) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..CELLS.main.circles_sized': GeoDataFrame shape: (2301, 2) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..REGIONS.Demo': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..REGIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..REGIONS.TMA': GeoDataFrame shape: (1, 7) (2D shapes)
│     ├── 'SAMPLE.9b82bec1..REGIONS.demo_regions': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..ANNOTATIONS.Demo': GeoDataFrame shape: (3, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..ANNOTATIONS.Janesick': GeoDataFrame shape: (2, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..ANNOTATIONS.Katja': GeoDataFrame shape: (2, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..ANNOTATIONS.demo2': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..CELLS.main.circles': GeoDataFrame shape: (3405, 2) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..CELLS.main.circles_sized': GeoDataFrame shape: (3405, 2) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..REGIONS.Demo': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..REGIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.70c2bfd8..REGIONS.TMA': GeoDataFrame shape: (1, 7) (2D shapes)
│     ├── 'SAMPLE.77d55bd5..ANNOTATIONS.Janesick': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.77d55bd5..ANNOTATIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.77d55bd5..CELLS.main.circles': GeoDataFrame shape: (1807, 2) (2D shapes)
│     ├── 'SAMPLE.77d55bd5..CELLS.main.circles_sized': GeoDataFrame shape: (1807, 2) (2D shapes)
│     ├── 'SAMPLE.77d55bd5..REGIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.77d55bd5..REGIONS.TMA': GeoDataFrame shape: (1, 7) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..ANNOTATIONS.Demo': GeoDataFrame shape: (4, 6) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..ANNOTATIONS.Janesick': GeoDataFrame shape: (2, 6) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..ANNOTATIONS.Katja': GeoDataFrame shape: (2, 6) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..CELLS.main.circles': GeoDataFrame shape: (4847, 2) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..CELLS.main.circles_sized': GeoDataFrame shape: (4847, 2) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..REGIONS.Demo': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..REGIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.92dc76ed..REGIONS.TMA': GeoDataFrame shape: (1, 7) (2D shapes)
│     ├── 'SAMPLE.c9d5337d..ANNOTATIONS.Janesick': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.c9d5337d..ANNOTATIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.c9d5337d..CELLS.main.circles': GeoDataFrame shape: (1766, 2) (2D shapes)
│     ├── 'SAMPLE.c9d5337d..CELLS.main.circles_sized': GeoDataFrame shape: (1766, 2) (2D shapes)
│     ├── 'SAMPLE.c9d5337d..REGIONS.TMA': GeoDataFrame shape: (1, 7) (2D shapes)
│     ├── 'SAMPLE.fda64ed4..ANNOTATIONS.Janesick': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.fda64ed4..ANNOTATIONS.Katja': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.fda64ed4..ANNOTATIONS.demo2': GeoDataFrame shape: (1, 6) (2D shapes)
│     ├── 'SAMPLE.fda64ed4..CELLS.main.circles': GeoDataFrame shape: (3569, 2) (2D shapes)
│     ├── 'SAMPLE.fda64ed4..CELLS.main.circles_sized': GeoDataFrame shape: (3569, 2) (2D shapes)
│     └── 'SAMPLE.fda64ed4..REGIONS.TMA': GeoDataFrame shape: (1, 7) (2D shapes)
└── Tables
      ├── 'SAMPLE.9b82bec1..CELLS.main.table': AnnData (2301, 297)
      ├── 'SAMPLE.70c2bfd8..CELLS.main.table': AnnData (3405, 297)
      ├── 'SAMPLE.77d55bd5..CELLS.main.table': AnnData (1807, 297)
      ├── 'SAMPLE.92dc76ed..CELLS.main.table': AnnData (4847, 297)
      ├── 'SAMPLE.c9d5337d..CELLS.main.table': AnnData (1766, 297)
      └── 'SAMPLE.fda64ed4..CELLS.main.table': AnnData (3569, 297)
with coordinate systems:
    ▸ 'global', with elements:
        SAMPLE.9b82bec1..IMAGES.CD20 (Images), SAMPLE.9b82bec1..IMAGES.HE (Images), SAMPLE.9b82bec1..IMAGES.HER2 (Images), SAMPLE.9b82bec1..IMAGES.nuclei (Images), SAMPLE.70c2bfd8..IMAGES.CD20 (Images), SAMPLE.70c2bfd8..IMAGES.HE (Images), SAMPLE.70c2bfd8..IMAGES.HER2 (Images), SAMPLE.70c2bfd8..IMAGES.nuclei (Images), SAMPLE.77d55bd5..IMAGES.CD20 (Images), SAMPLE.77d55bd5..IMAGES.HE (Images), SAMPLE.77d55bd5..IMAGES.HER2 (Images), SAMPLE.77d55bd5..IMAGES.nuclei (Images), SAMPLE.92dc76ed..IMAGES.CD20 (Images), SAMPLE.92dc76ed..IMAGES.HE (Images), SAMPLE.92dc76ed..IMAGES.HER2 (Images), SAMPLE.92dc76ed..IMAGES.nuclei (Images), SAMPLE.c9d5337d..IMAGES.CD20 (Images), SAMPLE.c9d5337d..IMAGES.HE (Images), SAMPLE.c9d5337d..IMAGES.HER2 (Images), SAMPLE.c9d5337d..IMAGES.nuclei (Images), SAMPLE.fda64ed4..IMAGES.CD20 (Images), SAMPLE.fda64ed4..IMAGES.HE (Images), SAMPLE.fda64ed4..IMAGES.HER2 (Images), SAMPLE.fda64ed4..IMAGES.nuclei (Images), SAMPLE.9b82bec1..CELLS.main.boundaries.cells (Labels), SAMPLE.9b82bec1..CELLS.main.boundaries.nuclei (Labels), SAMPLE.70c2bfd8..CELLS.main.boundaries.cells (Labels), SAMPLE.70c2bfd8..CELLS.main.boundaries.nuclei (Labels), SAMPLE.77d55bd5..CELLS.main.boundaries.cells (Labels), SAMPLE.77d55bd5..CELLS.main.boundaries.nuclei (Labels), SAMPLE.92dc76ed..CELLS.main.boundaries.cells (Labels), SAMPLE.92dc76ed..CELLS.main.boundaries.nuclei (Labels), SAMPLE.c9d5337d..CELLS.main.boundaries.cells (Labels), SAMPLE.c9d5337d..CELLS.main.boundaries.nuclei (Labels), SAMPLE.fda64ed4..CELLS.main.boundaries.cells (Labels), SAMPLE.fda64ed4..CELLS.main.boundaries.nuclei (Labels), SAMPLE.9b82bec1..ANNOTATIONS.Demo (Shapes), SAMPLE.9b82bec1..ANNOTATIONS.Janesick (Shapes), SAMPLE.9b82bec1..ANNOTATIONS.Katja (Shapes), SAMPLE.9b82bec1..ANNOTATIONS.TestKey (Shapes), SAMPLE.9b82bec1..ANNOTATIONS.demo2 (Shapes), SAMPLE.9b82bec1..CELLS.main.circles (Shapes), SAMPLE.9b82bec1..CELLS.main.circles_sized (Shapes), SAMPLE.9b82bec1..REGIONS.Demo (Shapes), SAMPLE.9b82bec1..REGIONS.Katja (Shapes), SAMPLE.9b82bec1..REGIONS.TMA (Shapes), SAMPLE.9b82bec1..REGIONS.demo_regions (Shapes), SAMPLE.70c2bfd8..ANNOTATIONS.Demo (Shapes), SAMPLE.70c2bfd8..ANNOTATIONS.Janesick (Shapes), SAMPLE.70c2bfd8..ANNOTATIONS.Katja (Shapes), SAMPLE.70c2bfd8..ANNOTATIONS.demo2 (Shapes), SAMPLE.70c2bfd8..CELLS.main.circles (Shapes), SAMPLE.70c2bfd8..CELLS.main.circles_sized (Shapes), SAMPLE.70c2bfd8..REGIONS.Demo (Shapes), SAMPLE.70c2bfd8..REGIONS.Katja (Shapes), SAMPLE.70c2bfd8..REGIONS.TMA (Shapes), SAMPLE.77d55bd5..ANNOTATIONS.Janesick (Shapes), SAMPLE.77d55bd5..ANNOTATIONS.Katja (Shapes), SAMPLE.77d55bd5..CELLS.main.circles (Shapes), SAMPLE.77d55bd5..CELLS.main.circles_sized (Shapes), SAMPLE.77d55bd5..REGIONS.Katja (Shapes), SAMPLE.77d55bd5..REGIONS.TMA (Shapes), SAMPLE.92dc76ed..ANNOTATIONS.Demo (Shapes), SAMPLE.92dc76ed..ANNOTATIONS.Janesick (Shapes), SAMPLE.92dc76ed..ANNOTATIONS.Katja (Shapes), SAMPLE.92dc76ed..CELLS.main.circles (Shapes), SAMPLE.92dc76ed..CELLS.main.circles_sized (Shapes), SAMPLE.92dc76ed..REGIONS.Demo (Shapes), SAMPLE.92dc76ed..REGIONS.Katja (Shapes), SAMPLE.92dc76ed..REGIONS.TMA (Shapes), SAMPLE.c9d5337d..ANNOTATIONS.Janesick (Shapes), SAMPLE.c9d5337d..ANNOTATIONS.Katja (Shapes), SAMPLE.c9d5337d..CELLS.main.circles (Shapes), SAMPLE.c9d5337d..CELLS.main.circles_sized (Shapes), SAMPLE.c9d5337d..REGIONS.TMA (Shapes), SAMPLE.fda64ed4..ANNOTATIONS.Janesick (Shapes), SAMPLE.fda64ed4..ANNOTATIONS.Katja (Shapes), SAMPLE.fda64ed4..ANNOTATIONS.demo2 (Shapes), SAMPLE.fda64ed4..CELLS.main.circles (Shapes), SAMPLE.fda64ed4..CELLS.main.circles_sized (Shapes), SAMPLE.fda64ed4..REGIONS.TMA (Shapes)

Saving and Loading SpatialData#

SpatialData objects can be saved to disk in Zarr format for efficient storage and lazy loading.

# Define output paths
outpath = CACHE / "test_spatialdata.zarr"
exp_outpath = CACHE / "exp_spatialdata.zarr"
# Save single sample SpatialData
sdata.write(outpath, overwrite=True)
print(f"Saved to: {outpath}")
Saved to: C:\Users\ge37voy\.cache\InSituPy\test_spatialdata.zarr
# Save experiment SpatialData
sdexp.write(exp_outpath, overwrite=True)
print(f"Saved to: {exp_outpath}")
Saved to: C:\Users\ge37voy\.cache\InSituPy\exp_spatialdata.zarr

Load from Disk#

from spatialdata import SpatialData

# Load saved SpatialData
sdata_loaded = SpatialData.read(outpath)
sdata_loaded
SpatialData object, with associated Zarr store: C:\Users\ge37voy\.cache\InSituPy\test_spatialdata.zarr
├── Images
│     ├── 'IMAGES.CD20': DataTree[cyx] (1, 25778, 35416), (1, 12889, 17708), (1, 6444, 8854), (1, 3222, 4427), (1, 1611, 2213), (1, 805, 1106)
│     ├── 'IMAGES.HE': DataTree[cyx] (3, 25778, 35416), (3, 12889, 17708), (3, 6444, 8854), (3, 3222, 4427), (3, 1611, 2213), (3, 805, 1106)
│     ├── 'IMAGES.HER2': DataTree[cyx] (1, 25778, 35416), (1, 12889, 17708), (1, 6444, 8854), (1, 3222, 4427), (1, 1611, 2213), (1, 805, 1106)
│     └── 'IMAGES.nuclei': DataTree[cyx] (1, 25778, 35416), (1, 12889, 17708), (1, 6444, 8854), (1, 3222, 4427), (1, 1611, 2213), (1, 805, 1106)
├── Labels
│     ├── 'CELLS.main.boundaries.cells': DataTree[yx] (25778, 35416), (12889, 17708), (6444, 8854), (3222, 4427), (1611, 2213), (805, 1106)
│     └── 'CELLS.main.boundaries.nuclei': DataTree[yx] (25778, 35416), (12889, 17708), (6444, 8854), (3222, 4427), (1611, 2213), (805, 1106)
├── Shapes
│     ├── 'ANNOTATIONS.Demo': GeoDataFrame shape: (28, 6) (2D shapes)
│     ├── 'ANNOTATIONS.Janesick': GeoDataFrame shape: (18, 6) (2D shapes)
│     ├── 'ANNOTATIONS.Katja': GeoDataFrame shape: (18, 6) (2D shapes)
│     ├── 'ANNOTATIONS.TestKey': GeoDataFrame shape: (9, 6) (2D shapes)
│     ├── 'ANNOTATIONS.demo2': GeoDataFrame shape: (5, 6) (2D shapes)
│     ├── 'ANNOTATIONS.demo3': GeoDataFrame shape: (7, 6) (2D shapes)
│     ├── 'CELLS.main.circles': GeoDataFrame shape: (156447, 2) (2D shapes)
│     ├── 'CELLS.main.circles_sized': GeoDataFrame shape: (156447, 2) (2D shapes)
│     ├── 'REGIONS.Demo': GeoDataFrame shape: (3, 6) (2D shapes)
│     ├── 'REGIONS.Katja': GeoDataFrame shape: (4, 6) (2D shapes)
│     ├── 'REGIONS.TMA': GeoDataFrame shape: (6, 7) (2D shapes)
│     └── 'REGIONS.demo_regions': GeoDataFrame shape: (3, 6) (2D shapes)
└── Tables
      └── 'CELLS.main.table': AnnData (156447, 297)
with coordinate systems:
    ▸ 'global', with elements:
        IMAGES.CD20 (Images), IMAGES.HE (Images), IMAGES.HER2 (Images), IMAGES.nuclei (Images), CELLS.main.boundaries.cells (Labels), CELLS.main.boundaries.nuclei (Labels), ANNOTATIONS.Demo (Shapes), ANNOTATIONS.Janesick (Shapes), ANNOTATIONS.Katja (Shapes), ANNOTATIONS.TestKey (Shapes), ANNOTATIONS.demo2 (Shapes), ANNOTATIONS.demo3 (Shapes), CELLS.main.circles (Shapes), CELLS.main.circles_sized (Shapes), REGIONS.Demo (Shapes), REGIONS.Katja (Shapes), REGIONS.TMA (Shapes), REGIONS.demo_regions (Shapes)