Data formats

MERFISHEYES reads the raw outputs of the common spatial platforms, so you don't need to pre-format anything. Drop a whole folder or a single file on the homepage; the format is worked out from what is inside.

At a glance

FormatWhat to dropRequiredAlso read if present
H5AD (AnnData)A single .h5ad fileCoordinates in obsm['X_spatial']Embeddings such as obsm['X_umap'], and any cell type or metadata columns in obs
Xenium (10x)The Xenium output foldercells.csv(.gz) — the cell centroidsAn expression matrix (cell_feature_matrix.h5, the cell_feature_matrix/ folder, or cell_by_gene.csv); a transcripts file is read as molecules
MERSCOPE (Vizgen)The MERSCOPE output foldercell_metadata.csv — per-cell coordinatescell_by_gene.csv (expression matrix)
MoleculesOne .parquet or .csv of per-molecule rowsA gene column, x and y (z for 3D data)A cell id column
ImageAn OME-Zarr image folderZarr v3, axes c, y, x; uint8 or uint16Several resolution levels
Already processedA SpatialData store, an AnnData table in Zarr, or merfisheyes' own output foldersSee the tabs belowOpens as it is — nothing is converted

Format by format

Each tab shows the folder or file as it should look, which parts are required, and anything to watch out for. The same guide opens from What can I upload? on the homepage.

An AnnData file. Cells need coordinates; everything else is optional.

Upload: One .h5ad file → H5AD File

  • data.h5ad
    • obsm/X_spatialrequiredCell coordinates, [cells × 2] or [cells × 3]. obsm/spatial also works.
    • XoptionalExpression matrix, [cells × genes], dense or sparse. Needed to colour by gene.
    • var/_indexoptionalGene names (var/gene or var/genes also work).
    • obs/<column>optionalCell types, clusters and other per-cell values — each becomes a colour-by column.
    • obsm/X_umapoptionalEmbeddings: any obsm key starting with X_.
    • uns/<column>_colorsoptionalYour own colours for a categorical column.

Making it yourself

From an AnnData (e.g. from Scanpy), or built from arrays

import anndata as ad
import pandas as pd

# counts: cells × genes (NumPy array or SciPy sparse matrix)
# xy: cells × 2 (or × 3) coordinates, e.g. in microns
adata = ad.AnnData(
    X=counts,
    obs=pd.DataFrame({"celltype": celltypes}, index=cell_ids),
    var=pd.DataFrame(index=gene_names),
)
adata.obsm["X_spatial"] = xy      # required
adata.obsm["X_umap"] = umap       # optional

adata.write_h5ad("data.h5ad")
  • No coordinates in obsm? obs columns named center_x / center_y, x / y or centroid_x / centroid_y are used instead.
  • A column with few distinct values is shown as categories; one with many numeric values as a gradient. Columns named leiden or louvain are always categories.

Molecule columns

Column names are detected per platform, and you can remap them when you upload. Parquet is strongly preferred for millions of molecules: it is columnar and needs far less memory than CSV.

PlatformGeneXYZCell ID
Xeniumfeature_namex_locationy_locationz_locationcell_id (UNASSIGNED = no cell)
MERSCOPEgeneglobal_xglobal_yglobal_zcell_id (-1 = no cell)
CustomYou pick each column from a dropdown

Cell types you assigned yourself

Cell types don't have to be in the file. Run MapMyCells (or any tool) yourself, then choose Upload & process on server and add the resulting one-row-per-cell CSV in the MapMyCells celltype CSV (optional) box on the homepage. Its columns become columns to colour by, with their own palettes and differential expression. There is no cell typing on our side, so the labels stay yours.

The CSV has one row per cell, in the same order as the cells in your data, with a cell_id column first and one column per label. From an AnnData:

adata.obs[["my_celltype"]].to_csv("celltypes.csv", index_label="cell_id")
An image is drawn under cells only when the cells kept their original coordinates (usually microns). Folders written by older versions of the Python scripts normalized them; they still load, but an image can't be placed under them.