Preparing your spatial data for Spatial Studio

Last updated: August 20, 2026

Written by Caitlin Winkler, Ph.D.

Spatial Studio is where you visualize and interrogate your spatial transcriptomics data in Pluto. This guide covers what to upload and what Pluto does to your data.


Accessing Spatial Studio from a Program Dataset

Before you upload

Spatial Studio is a visualization and exploration tool. You bring a fully processed dataset and Pluto displays it faithfully, adds standard exploratory statistics, and lets you annotate your clusters. Pluto does not re-process your data or make analytical decisions for you.

Your spatial dataset must adhere to the following format requirements:

Requirement

Format

A single AnnData .h5ad file. This is the only supported format.

Expression

Filtered, normalized, and log-transformed values in X.

Clustering

A cluster assignment column in obs. You map it during upload and it is required.

Coordinates

Cell or spot coordinates in obsm['spatial'].

Samples

A Sample ID column in obs. You map it during upload. One or more samples per experiment; multiple samples are jointly clustered and viewed one at a time.

NOTE: Gene symbols in var are recommended so genes display by name. If your index holds Ensembl IDs and var has a symbol column, Pluto will swap symbols into the index and keep the original IDs.

Supported platforms. 10x Genomics Visium, 10x Genomics Xenium, Vizgen MERFISH, Slide-seq, and generic H5AD. You confirm the platform during the mapping step.

Not accepted. FASTQ or other raw sequencing data, and raw count matrices such as a 10x .h5 feature-barcode matrix. Spatial Studio needs processed data.

Multiple Samples. A single experiment can hold multiple biological samples in one .h5ad. Each cell is assigned to a sample by the Sample ID you map during upload. Samples are jointly clustered into one shared set of clusters and a shared UMAP, and you view one at a time in the viewer. You can compare across samples with cross-sample differential expression and per-sample composition.

NOTE: Samples and sections are two different things, and the distinction matters if you have serial sections.

A sample is a biological unit, identified by the Sample ID you map. A section is a physical piece of tissue on a slide. One sample can span several sections, and each section is what carries its own tissue image and its own coordinate space. Spatial Studio keeps them separate deliberately: coordinates are normalized per section, and the spatial neighbor graph is built per section, so two sections of the same sample are never treated as one continuous piece of tissue. Sections without an image are fully supported and render as a coordinate plot.

On Visium, the capture area is larger than the tissue, so a standard object includes spots outside it, marked in_tissue = 0. Spatial Studio excludes those from rendering, from the plot bounds, from spot sizing, and from hit-testing, so your tissue fills the view and off-tissue spots do not skew the display.

An object with no in_tissue column, which is normal on non-Visium platforms, renders every spot.

Tissue images. If your object embeds its image, or carries coordinates only, an image upload is optional and your data renders as a coordinate plot. If your object references an image file that is not present, you will be prompted to upload one. Accepted formats are OME-ZARR, OME-TIFF (.ome.tif / .ome.tiff), and SpatialData ZARR.

If a region’s image is missing when you expected one, Pluto verifies each image pyramid is complete before publishing it and discards any that fails, so the region falls back to a coordinate plot rather than showing a broken image. Re-running the pipeline usually resolves it. If it does not, contact us with the dataset ID rather than re-uploading.


Three things worth checking before you save

These are the most common reasons an upload behaves differently than expected. All three are avoidable in one line of your own code.

Clustering has to be in the object

Spatial Studio requires a cluster column and will not generate one. This is deliberate: clusters Pluto invented would look like yours and could be misread. Cluster your data in your own workflow first.

TIP: Your clusters do not need labels before upload. Numbered clusters are fine, and you can annotate them in Pluto later.

Save un-scaled values in X

Many scanpy workflows end with sc.pp.scale(), which centers expression and leaves negative values in X. Negative values cannot be log-normalized, so Pluto will not use that matrix. Instead it looks for your pre-scaling values in this order:

  1. adata.raw

  2. adata.layers['counts']

  3. a single layer that reads as log-normalized

If it finds one, your upload succeeds and Spatial Studio tells you which matrix your displayed values came from. If it finds nothing usable, the upload fails with a clear message rather than showing you broken numbers.

TIP: To avoid the ambiguity, save with un-scaled log-normalized values in X, keeping the scaled matrix in a layer if you want it. Setting adata.raw before you scale also works, and the standard scanpy tutorial already does this.

Decide whether you want your full gene panel

The standard highly variable gene workflow does adata.raw = adata and then subsets to the top few thousand genes. If you save after that step, your uploaded object holds a fraction of your panel, and a gene missing from the truncated list looks exactly like a gene that was not detected.

Spatial Studio flags this in the header when it can tell. If you want your whole panel searchable, save without the HVG subset. Your clustering and embeddings are unaffected either way.


What Pluto does to your data

The ingestion pipeline

  • Validates your object: coordinates present, a cluster column present, readable expression.

  • Guarantees a normalized layer. It detects whether your expression is raw counts, normalized, or log-normalized, and produces - if needed - one consistent log-normalized layer that every plot and statistic reads from.

  • Records what it did, so the viewer can report it back to you.

  • Computes marker genes for each of your clusters, using a standard one-versus-rest Wilcoxon test.

  • Computes spatial statistics (Moran’s I) and builds the per-section spatial neighbor graph.

  • Packages a bundle so the viewer loads quickly.

What Pluto does not do

  • Does not cluster your data. Clusters come from you.

  • Does not assign cell types. You label your clusters on the Annotations page, with CellKB assistance if you want it.

  • Does not re-normalize data that is already normalized, and does not choose a normalization strategy for you beyond a standard default.

  • Does not recompute clusters, markers, or normalization inside the viewer. Spatial Studio reads what the pipeline produced. When clusters are merged in the viewer (see "Naming and coloring your clusters"), the merged group does not exist when the pipeline ran, so there are no precomputed markers to read, and Spatial Studio can compute them on demand.

Normalization, precisely

The pipeline acts on the state of your data, not on the platform label:

  • Raw counts are normalized to 10,000 counts per cell (CP10K) and log-transformed.

  • Already normalized data is only log-transformed.

  • Already log-normalized data is passed through unchanged.

Detection does not assume a particular scale. If you normalized to counts-per-million, or to your own dataset’s median library size, your data is recognized as already normalized rather than being normalized a second time.

A note on imaging platforms

When Pluto normalizes raw counts itself, it uses total-count normalization. On imaging-based assays such as Xenium and MERFISH, total-count normalization can be confounded by cell size, because a larger cell yields more transcripts regardless of biology. Atta et al., Genome Biology 2024, “Gene count normalization in single-cell imaging-based spatially resolved transcriptomics”, documents how this bias propagates into differential expression calls, fold changes, and spatially variable gene detection.

Spatial Studio surfaces this note in the viewer when it applies. Pluto does not choose a non-count-based normalization on your behalf. If you want one, apply it before upload and Pluto will respect your values.


FAQs

Do you re-normalize or re-cluster my data? 

Never re-cluster; clustering must come from you. For normalization, Pluto guarantees one consistent log-normalized layer: already-normalized data is only log-transformed, already log-normalized data is passed through, and only raw counts get CP10K plus log1p. Whichever happened is stated in the viewer’s top bar.

Can I upload multiple samples in one file? 

Yes. A single experiment can hold multiple biological samples in one .h5ad. Each cell is assigned to a sample by the Sample ID you map during upload, samples are jointly clustered into one shared UMAP, and you view one sample at a time. Cross-sample differential expression and per-sample composition let you compare across samples.

What normalization should I use for Xenium or MERFISH? 

If you have a preference, apply it before upload and Pluto will respect it. See the note on imaging platforms above for why this matters.


Quick checklist

Before you upload:

  • [ ] Single .h5ad file

  • [ ] Filtered, normalized, log-transformed values in X

  • [ ] No negative values in X (not scaled or z-scored)

  • [ ] Cluster column present in obs

  • [ ] Coordinates in obsm['spatial']

  • [ ] Sample ID column in obs (one or more samples)

  • [ ] Full gene panel, if you want every gene searchable

  • [ ] Gene symbols in var (recommended)

  • [ ] Tissue image ready, if your object references one

  • [ ] in_tissue column present, if you are on Visium and want off-tissue spots excluded


🚀 Ready to explore your spatial data?

We hope that the guide above helps you feel confident in uploading your data for exploration. Up next: visit our 'Exploring spatial data in Spatial Studio' for guidance in interpreting the statistics in the viewer. For more resources, we encourage you to take a look at our Blog and Knowledge Base.

Please reach out to support@pluto.bio if you have additional questions.

As always, our scientific support team is here to help! 🧬