# AnnData Stores

AnnData is the convention single-cell and spatial biology tools use to keep a measurement matrix together with its annotations. Written to Zarr, it becomes a group hierarchy with fixed member names: `X` holds the main matrix, `obs` describes the observations (cells or spots), `var` describes the variables (genes), and `obsm` holds alternative per-observation representations such as embeddings.

Reading one is a matter of knowing those names. The example here is a 10x Visium human lymph node section published by Vitessce, read over HTTPS — see `vignette("remote-stores")` for connection details.

## Opening the store

This store publishes no consolidated metadata, so pizzarr cannot list what it contains — an HTTP server offers no equivalent of `ls`. That is the normal case for AnnData stores, and it is workable only because the member names are fixed by the convention: you address `obs`, `obsm`, and `X` by name rather than discovering them.

    g <- zarr_open_group(HttpStore$new(root))

## Observation annotations

`obs` is a group, not an array. Which of its members holds the observation identifiers is recorded in its `_index` attribute rather than fixed by name, so the lookup goes through the attributes:

    obs_attrs <- g$get_item("obs")$get_attrs()$to_list()
    index_colname <- obs_attrs[["_index"]]
    index_colname

    index_arr <- g$get_item(paste0("obs/", index_colname))$get_item("...")$data

    length(index_arr)
    head(index_arr, 3)

Those are barcodes identifying the 3861 spots on the slide. Cluster assignments live alongside them under the same group:

    cluster_arr <- g$get_item("obs/clusters")$get_item("...")$data

    table(cluster_arr)

## Embeddings

`obsm` holds per-observation matrices — one row per spot, as many columns as the representation needs. A UMAP embedding is two columns:

    umap_arr <- g$get_item("obsm/X_umap")$get_item("...")$data

    dim(umap_arr)

Plotting the embedding coloured by cluster gives the standard view of this kind of dataset:

    plot(umap_arr[, 1], umap_arr[, 2],
         col = as.integer(as.factor(cluster_arr)),
         pch = 19, cex = 0.4,
         xlab = "UMAP 1", ylab = "UMAP 2")