From 0129366cb5e40de55d09b958891e6c2faf9187f4 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 22 Jun 2026 13:28:21 +0200 Subject: [PATCH 1/4] feat: 0.13 blog post --- content/blog/2026-anndata-013.md | 81 ++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 content/blog/2026-anndata-013.md diff --git a/content/blog/2026-anndata-013.md b/content/blog/2026-anndata-013.md new file mode 100644 index 0000000..8cbcc5b --- /dev/null +++ b/content/blog/2026-anndata-013.md @@ -0,0 +1,81 @@ ++++ +title = "anndata 0.13: `layers` meets `X`, zarr v3, and accessors" +date = 2026-06-18T10:30:00+01:00 +description = "anndata 0.13 moves X into layers, makes zarr v3 the default, and introduces accessors for object-independent array references." +author = "Ilan Gold" +draft = true ++++ + +# 0.13 released + +We're thrilled to announce that `anndata` 0.13 is out now! +We'll highlight some of the major changes here but be sure to check out [the changelog](https://anndata.scverse.org/en/latest/release-notes/) for the full list of changes, including breaking changes. + +## `X` is now a layer + +The biggest conceptual change in 0.13 is that the main expression matrix `X` is now stored as a layer, internally `layers[None]`. +For most code this is invisible since you still access/read/write `adata.X` exactly as before. +But treating `X` as just another layer moves us towards encouraging our users to be explicit about what `X` really is. +Towards this end, our support for accessor objects (see below) will hopefully help make it easier for packages to declare what layers they expect to produce/consume. +One **major breaking change** you will notice here is that anything relying on the keys of `layers` being all strings will now need to handle `None` as a key. + +### Copy-on-write for `X ` +As `X` is now a layer, writing into a view's `X` no longer mutates the parent `X`. +This now matches how every other element (`obsm`, `var` etc.) already behaved: + +```python +view = adata[:100] +view.X = 0 # does NOT modify adata.X anymore, instead instantiates `view` as a fully in-memory `AnnData` object +``` + +If you were relying on the old propagating behavior, operate on the original object directly. + +## Zarr v3 by default + +We introduced support for the zarr v3 file-format as well as the v3 `zarr-python` package in [0.12](/blog/2025-anndata-012/). +In 0.13 the file format v3 becomes the default, and support for `zarr-python<3` (i.e., the python package) is dropped entirely, however you can still opt-in to write v2 data. + +Concretely: + +- `anndata.settings.zarr_write_format` now defaults to `3` so all `write_zarr` calls in which the argument is a string file path will be v3 +- Automatic sharding is on by default (`anndata.settings.auto_shard_zarr_v3` targeting ~1GB uncompressed shards), so you get far fewer files per store with no manual tuning. + +If you want a refresher on what zarr v3 buys you, sharding to avoid file-system slowdowns, concurrent/parallel io, tips/tricks, and using rust-accelerated tooling like [zarrs-python](https://zarrs-python.readthedocs.io/en/latest/), the [zarr v3 guide](https://anndata.scverse.org/en/stable/tutorials/zarr-v3.html) and our [0.12 post](/blog/2025-anndata-012/) cover it in depth. +If `zarrs` is installed in your environment the bulk read/write functions i.e., `anndata.read_zarr` and `AnnData.write_zarr` will use it. + +## Accessors: object-independent array references + +0.13 introduces the new [`anndata.acc`](https://anndata.scverse.org/en/latest/accessors.html) module for referring to a vector or array *by location* without binding it to a specific object. + +The use cases for this feature abound: plotting functionality, validation, or arguments for things like "the `louvain` column" or "the first PCA component". +Until now you'd pass around strings inlined into functions. +Accessors now make these references first-class, fully supported objects that your package can export to users. + +You build references through the global `A` accessor: + +```python +from anndata.acc import A + +A.X[:, "gene-3"] # expression of one gene +A.obsm["pca"][:, 0] # first PCA component +A.obs["louvain"] # a cell-level annotation +``` + +These `AdRef` objects are independent of any AnnData instance. +Furthermore you can inspect them (`.dims`, `.idx`, `.acc`), compare them for equality and use them as dictionary keys. +To resolve a reference against an actual object i.e., index with it or test membership: + +```python +ref = A.obs["louvain"] +adata[ref] # indexes the anndata object, materializing an array +A.varm["PCs"][:, 30] in adata # answeres "does this reference exist here?" without loading the data +``` + +Accessors also work with `MuData` and are subclassable if you need custom behavior. + +If you are interested in schemas for `AnnData` please get in touch - we support [rudimentary serialization][] of accessors and have a schema for this output, but it can definitely be richer. +Check it out and open an issue if you are interested! + +*— The scverse core team* + +[rudimentary *serialization*]: https://anndata.scverse.org/en/latest/generated/anndata.acc.AdAcc.html#anndata.acc.AdAcc.to_json From fb68267b6b627dd5a00f27b3fe966b6720401900 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 22 Jun 2026 13:34:55 +0200 Subject: [PATCH 2/4] fixes --- content/blog/2026-anndata-013.md | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/content/blog/2026-anndata-013.md b/content/blog/2026-anndata-013.md index 8cbcc5b..1697ce5 100644 --- a/content/blog/2026-anndata-013.md +++ b/content/blog/2026-anndata-013.md @@ -1,25 +1,23 @@ +++ -title = "anndata 0.13: `layers` meets `X`, zarr v3, and accessors" +title = "anndata 0.13: layers meets X, zarr v3, and accessors" date = 2026-06-18T10:30:00+01:00 description = "anndata 0.13 moves X into layers, makes zarr v3 the default, and introduces accessors for object-independent array references." author = "Ilan Gold" draft = true +++ -# 0.13 released - We're thrilled to announce that `anndata` 0.13 is out now! -We'll highlight some of the major changes here but be sure to check out [the changelog](https://anndata.scverse.org/en/latest/release-notes/) for the full list of changes, including breaking changes. +We'll highlight some of the major changes here but be sure to check out [the changelog][] for the full list of changes, including breaking changes. -## `X` is now a layer +# `X` is now a layer The biggest conceptual change in 0.13 is that the main expression matrix `X` is now stored as a layer, internally `layers[None]`. For most code this is invisible since you still access/read/write `adata.X` exactly as before. -But treating `X` as just another layer moves us towards encouraging our users to be explicit about what `X` really is. +But treating `X` as just another layer moves us towards encouraging our users to be explicit about what `X` really is while lightening our code burden and unfiying behavior. Towards this end, our support for accessor objects (see below) will hopefully help make it easier for packages to declare what layers they expect to produce/consume. One **major breaking change** you will notice here is that anything relying on the keys of `layers` being all strings will now need to handle `None` as a key. -### Copy-on-write for `X ` +## Copy-on-write for `X ` As `X` is now a layer, writing into a view's `X` no longer mutates the parent `X`. This now matches how every other element (`obsm`, `var` etc.) already behaved: @@ -30,9 +28,9 @@ view.X = 0 # does NOT modify adata.X anymore, instead instantiates `vie If you were relying on the old propagating behavior, operate on the original object directly. -## Zarr v3 by default +# Zarr v3 by default -We introduced support for the zarr v3 file-format as well as the v3 `zarr-python` package in [0.12](/blog/2025-anndata-012/). +We introduced support for the zarr v3 file-format as well as the v3 `zarr-python` package in 0.12. In 0.13 the file format v3 becomes the default, and support for `zarr-python<3` (i.e., the python package) is dropped entirely, however you can still opt-in to write v2 data. Concretely: @@ -40,12 +38,12 @@ Concretely: - `anndata.settings.zarr_write_format` now defaults to `3` so all `write_zarr` calls in which the argument is a string file path will be v3 - Automatic sharding is on by default (`anndata.settings.auto_shard_zarr_v3` targeting ~1GB uncompressed shards), so you get far fewer files per store with no manual tuning. -If you want a refresher on what zarr v3 buys you, sharding to avoid file-system slowdowns, concurrent/parallel io, tips/tricks, and using rust-accelerated tooling like [zarrs-python](https://zarrs-python.readthedocs.io/en/latest/), the [zarr v3 guide](https://anndata.scverse.org/en/stable/tutorials/zarr-v3.html) and our [0.12 post](/blog/2025-anndata-012/) cover it in depth. +If you want a refresher on what zarr v3 buys you, sharding to avoid file-system slowdowns, concurrent/parallel io, tips/tricks, and using rust-accelerated tooling like [zarrs-python][], the [zarr v3 guide][] and our [0.12 post][] cover it in depth. If `zarrs` is installed in your environment the bulk read/write functions i.e., `anndata.read_zarr` and `AnnData.write_zarr` will use it. -## Accessors: object-independent array references +# Accessors: object-independent array references -0.13 introduces the new [`anndata.acc`](https://anndata.scverse.org/en/latest/accessors.html) module for referring to a vector or array *by location* without binding it to a specific object. +0.13 introduces the new [`anndata.acc`][] module for referring to a vector or array *by location* without binding it to a specific object. The use cases for this feature abound: plotting functionality, validation, or arguments for things like "the `louvain` column" or "the first PCA component". Until now you'd pass around strings inlined into functions. @@ -78,4 +76,9 @@ Check it out and open an issue if you are interested! *— The scverse core team* -[rudimentary *serialization*]: https://anndata.scverse.org/en/latest/generated/anndata.acc.AdAcc.html#anndata.acc.AdAcc.to_json +[the changelog]: https://anndata.scverse.org/en/stable/release-notes/ +[zarrs-python]: https://zarrs-python.readthedocs.io/en/latest/ +[zarr v3 guide]: https://anndata.scverse.org/en/stable/tutorials/zarr-v3.html +[0.12 post]: /blog/2025-anndata-012/ +[`anndata.acc`]: https://anndata.scverse.org/en/latest/accessors.html +[rudimentary serialization]: https://anndata.scverse.org/en/latest/generated/anndata.acc.AdAcc.html#anndata.acc.AdAcc.to_json From 7cd40362e792e821c016b156036180d4617066f1 Mon Sep 17 00:00:00 2001 From: ilan-gold Date: Mon, 22 Jun 2026 13:40:05 +0200 Subject: [PATCH 3/4] no draft for rendering --- content/blog/2026-anndata-013.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2026-anndata-013.md b/content/blog/2026-anndata-013.md index 1697ce5..1d982e1 100644 --- a/content/blog/2026-anndata-013.md +++ b/content/blog/2026-anndata-013.md @@ -3,7 +3,7 @@ title = "anndata 0.13: layers meets X, zarr v3, and accessors" date = 2026-06-18T10:30:00+01:00 description = "anndata 0.13 moves X into layers, makes zarr v3 the default, and introduces accessors for object-independent array references." author = "Ilan Gold" -draft = true +draft = false +++ We're thrilled to announce that `anndata` 0.13 is out now! From 15d96fbe2c11be5130a045fba9ae3521f49c1e4a Mon Sep 17 00:00:00 2001 From: Ilan Gold Date: Mon, 22 Jun 2026 13:50:43 +0200 Subject: [PATCH 4/4] Update content/blog/2026-anndata-013.md Co-authored-by: Lukas Heumos --- content/blog/2026-anndata-013.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/blog/2026-anndata-013.md b/content/blog/2026-anndata-013.md index 1d982e1..04824c2 100644 --- a/content/blog/2026-anndata-013.md +++ b/content/blog/2026-anndata-013.md @@ -45,7 +45,7 @@ If `zarrs` is installed in your environment the bulk read/write functions i.e., 0.13 introduces the new [`anndata.acc`][] module for referring to a vector or array *by location* without binding it to a specific object. -The use cases for this feature abound: plotting functionality, validation, or arguments for things like "the `louvain` column" or "the first PCA component". +The use cases for this feature abound: plotting functionality, validation, or arguments for things like "the `leiden` column" or "the first PCA component". Until now you'd pass around strings inlined into functions. Accessors now make these references first-class, fully supported objects that your package can export to users.