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 sampleInSituExperiment: 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 allowdask-geopandasto be installed alongsidespatialdatain 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 imageCELLS.main.matrix- Main cell expression matrixCELLS.main.boundaries.cells- Cell boundary masksTRANSCRIPTS- Transcript point dataANNOTATIONS.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 Sample1SAMPLE.1f1bcf1f.CELLS.main.matrix- Cell matrix from Sample1SAMPLE.1f1bcf1f.IMAGES.CD20- CD20 image from Sample2SAMPLE.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)