anndata 0.12.6__tar.gz → 0.12.8__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. anndata-0.12.8/.cruft.json +43 -0
  2. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/test-cpu.yml +10 -9
  3. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/test-gpu.yml +3 -2
  4. {anndata-0.12.6 → anndata-0.12.8}/.pre-commit-config.yaml +2 -2
  5. {anndata-0.12.6 → anndata-0.12.8}/.readthedocs.yml +1 -1
  6. {anndata-0.12.6 → anndata-0.12.8}/PKG-INFO +7 -7
  7. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/dataset2d.py +17 -4
  8. {anndata-0.12.6 → anndata-0.12.8}/docs/_key_contributors.rst +3 -4
  9. {anndata-0.12.6 → anndata-0.12.8}/docs/concatenation.rst +2 -2
  10. {anndata-0.12.6 → anndata-0.12.8}/docs/conf.py +7 -5
  11. {anndata-0.12.6 → anndata-0.12.8}/docs/fileformat-prose.md +39 -8
  12. anndata-0.12.8/docs/index.md +21 -0
  13. {anndata-0.12.6 → anndata-0.12.8}/docs/references.rst +0 -5
  14. anndata-0.12.8/docs/release-notes/0.12.7.md +12 -0
  15. anndata-0.12.8/docs/release-notes/0.12.8.md +10 -0
  16. {anndata-0.12.6 → anndata-0.12.8}/docs/tutorials/zarr-v3.md +16 -6
  17. {anndata-0.12.6 → anndata-0.12.8}/hatch.toml +2 -4
  18. {anndata-0.12.6 → anndata-0.12.8}/pyproject.toml +10 -14
  19. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/aligned_df.py +5 -5
  20. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/anndata.py +31 -16
  21. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/index.py +14 -12
  22. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/merge.py +79 -92
  23. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/sparse_dataset.py +11 -2
  24. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/views.py +1 -0
  25. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/xarray.py +75 -31
  26. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/h5ad.py +5 -4
  27. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/read.py +3 -3
  28. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/specs/lazy_methods.py +32 -24
  29. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/specs/methods.py +50 -35
  30. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/utils.py +30 -1
  31. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/zarr.py +6 -2
  32. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_settings.py +3 -3
  33. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_types.py +2 -2
  34. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/compat/__init__.py +101 -13
  35. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/_dispatch_io.py +1 -4
  36. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/backed/_io.py +17 -11
  37. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/backed/_lazy_arrays.py +49 -45
  38. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/merge.py +85 -33
  39. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/multi_files/_anncollection.py +2 -2
  40. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/tests/helpers.py +18 -21
  41. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/utils.py +7 -7
  42. {anndata-0.12.6 → anndata-0.12.8}/src/testing/anndata/_pytest.py +2 -1
  43. {anndata-0.12.6 → anndata-0.12.8}/tests/conftest.py +8 -2
  44. anndata-0.12.8/tests/data/archives/v0.5.0/adata.h5ad +0 -0
  45. anndata-0.12.8/tests/data/archives/v0.5.0/readme.md +7 -0
  46. anndata-0.12.8/tests/lazy/__init__.py +0 -0
  47. {anndata-0.12.6 → anndata-0.12.8}/tests/lazy/conftest.py +7 -7
  48. {anndata-0.12.6 → anndata-0.12.8}/tests/lazy/test_concat.py +11 -7
  49. {anndata-0.12.6 → anndata-0.12.8}/tests/lazy/test_read.py +58 -6
  50. {anndata-0.12.6 → anndata-0.12.8}/tests/test_annot.py +1 -1
  51. {anndata-0.12.6 → anndata-0.12.8}/tests/test_backed_sparse.py +1 -0
  52. {anndata-0.12.6 → anndata-0.12.8}/tests/test_concatenate.py +29 -9
  53. {anndata-0.12.6 → anndata-0.12.8}/tests/test_concatenate_disk.py +61 -4
  54. {anndata-0.12.6 → anndata-0.12.8}/tests/test_dask.py +5 -7
  55. {anndata-0.12.6 → anndata-0.12.8}/tests/test_dask_view_mem.py +8 -4
  56. {anndata-0.12.6 → anndata-0.12.8}/tests/test_helpers.py +10 -2
  57. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_backwards_compat.py +10 -3
  58. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_elementwise.py +147 -33
  59. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_partial.py +5 -2
  60. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_warnings.py +4 -5
  61. {anndata-0.12.6 → anndata-0.12.8}/tests/test_layers.py +0 -24
  62. {anndata-0.12.6 → anndata-0.12.8}/tests/test_readwrite.py +62 -135
  63. {anndata-0.12.6 → anndata-0.12.8}/tests/test_utils.py +7 -5
  64. {anndata-0.12.6 → anndata-0.12.8}/tests/test_views.py +61 -5
  65. {anndata-0.12.6 → anndata-0.12.8}/tests/test_xarray.py +82 -22
  66. anndata-0.12.6/.prettierignore +0 -1
  67. anndata-0.12.6/.prettierrc.yaml +0 -7
  68. anndata-0.12.6/docs/index.md +0 -28
  69. anndata-0.12.6/docs/news.md +0 -10
  70. {anndata-0.12.6 → anndata-0.12.8}/.cirun.yml +0 -0
  71. {anndata-0.12.6 → anndata-0.12.8}/.codecov.yml +0 -0
  72. {anndata-0.12.6 → anndata-0.12.8}/.editorconfig +0 -0
  73. {anndata-0.12.6 → anndata-0.12.8}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  74. {anndata-0.12.6 → anndata-0.12.8}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  75. {anndata-0.12.6 → anndata-0.12.8}/.github/ISSUE_TEMPLATE/enhancement-request.yml +0 -0
  76. {anndata-0.12.6 → anndata-0.12.8}/.github/ISSUE_TEMPLATE/question.yml +0 -0
  77. {anndata-0.12.6 → anndata-0.12.8}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  78. {anndata-0.12.6 → anndata-0.12.8}/.github/dependabot.yml +0 -0
  79. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/benchmark.yml +0 -0
  80. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/check-pr.yml +0 -0
  81. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/close-stale.yml +0 -0
  82. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/codespell.yml +0 -0
  83. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/label-stale.yml +0 -0
  84. {anndata-0.12.6 → anndata-0.12.8}/.github/workflows/publish.yml +0 -0
  85. {anndata-0.12.6 → anndata-0.12.8}/.gitignore +0 -0
  86. {anndata-0.12.6 → anndata-0.12.8}/.gitmodules +0 -0
  87. {anndata-0.12.6 → anndata-0.12.8}/.taplo.toml +0 -0
  88. {anndata-0.12.6 → anndata-0.12.8}/.vscode/launch.json +0 -0
  89. {anndata-0.12.6 → anndata-0.12.8}/.vscode/settings.json +0 -0
  90. {anndata-0.12.6 → anndata-0.12.8}/LICENSE +0 -0
  91. {anndata-0.12.6 → anndata-0.12.8}/README.md +0 -0
  92. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/README.md +0 -0
  93. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/asv.conf.json +0 -0
  94. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/__init__.py +0 -0
  95. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/anndata.py +0 -0
  96. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/backed_hdf5.py +0 -0
  97. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/readwrite.py +0 -0
  98. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/sparse_dataset.py +0 -0
  99. {anndata-0.12.6 → anndata-0.12.8}/benchmarks/benchmarks/utils.py +0 -0
  100. {anndata-0.12.6 → anndata-0.12.8}/biome.jsonc +0 -0
  101. {anndata-0.12.6 → anndata-0.12.8}/ci/constraints.txt +0 -0
  102. {anndata-0.12.6 → anndata-0.12.8}/ci/min-constraints.txt +0 -0
  103. {anndata-0.12.6 → anndata-0.12.8}/ci/scripts/min-deps.py +0 -0
  104. {anndata-0.12.6 → anndata-0.12.8}/ci/scripts/towncrier_automation.py +0 -0
  105. {anndata-0.12.6 → anndata-0.12.8}/docs/Makefile +0 -0
  106. {anndata-0.12.6 → anndata-0.12.8}/docs/_static/img/anndata_schema.svg +0 -0
  107. {anndata-0.12.6 → anndata-0.12.8}/docs/_templates/autosummary/class.rst +0 -0
  108. {anndata-0.12.6 → anndata-0.12.8}/docs/api.md +0 -0
  109. {anndata-0.12.6 → anndata-0.12.8}/docs/benchmark-read-write.ipynb +0 -0
  110. {anndata-0.12.6 → anndata-0.12.8}/docs/benchmarks.md +0 -0
  111. {anndata-0.12.6 → anndata-0.12.8}/docs/contributing.md +0 -0
  112. {anndata-0.12.6 → anndata-0.12.8}/docs/extensions/autosummary_skip_inherited.py +0 -0
  113. {anndata-0.12.6 → anndata-0.12.8}/docs/extensions/no_skip_abc_members.py +0 -0
  114. {anndata-0.12.6 → anndata-0.12.8}/docs/extensions/patch_myst_cite.py +0 -0
  115. {anndata-0.12.6 → anndata-0.12.8}/docs/interoperability.md +0 -0
  116. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.0.md +0 -0
  117. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.1.md +0 -0
  118. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.2.md +0 -0
  119. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.3.md +0 -0
  120. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.4.md +0 -0
  121. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.5.md +0 -0
  122. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.6.md +0 -0
  123. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.7.md +0 -0
  124. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.8.md +0 -0
  125. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.10.9.md +0 -0
  126. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.11.0.md +0 -0
  127. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.11.1.md +0 -0
  128. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.11.2.md +0 -0
  129. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.11.3.md +0 -0
  130. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.11.4.md +0 -0
  131. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.0.md +0 -0
  132. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.1.md +0 -0
  133. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.2.md +0 -0
  134. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.3.md +0 -0
  135. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.4.md +0 -0
  136. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.5.md +0 -0
  137. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.12.6.md +0 -0
  138. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.4.0.md +0 -0
  139. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.5.0.md +0 -0
  140. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.6.0.md +0 -0
  141. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.6.x.md +0 -0
  142. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.0.md +0 -0
  143. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.2.md +0 -0
  144. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.3.md +0 -0
  145. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.4.md +0 -0
  146. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.5.md +0 -0
  147. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.6.md +0 -0
  148. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.7.md +0 -0
  149. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.7.8.md +0 -0
  150. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.8.0.md +0 -0
  151. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.9.0.md +0 -0
  152. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.9.1.md +0 -0
  153. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/0.9.2.md +0 -0
  154. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/2172.bug.md +0 -0
  155. {anndata-0.12.6 → anndata-0.12.8}/docs/release-notes/index.md +0 -0
  156. {anndata-0.12.6 → anndata-0.12.8}/docs/tutorials/index.md +0 -0
  157. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/__init__.py +0 -0
  158. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/__init__.py +0 -0
  159. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/access.py +0 -0
  160. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/aligned_mapping.py +0 -0
  161. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/extensions.py +0 -0
  162. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/file_backing.py +0 -0
  163. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/raw.py +0 -0
  164. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_core/storage.py +0 -0
  165. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/__init__.py +0 -0
  166. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/specs/__init__.py +0 -0
  167. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/specs/registry.py +0 -0
  168. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_io/write.py +0 -0
  169. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_settings.pyi +0 -0
  170. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/_warnings.py +0 -0
  171. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/abc.py +0 -0
  172. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/__init__.py +0 -0
  173. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/backed/__init__.py +0 -0
  174. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/backed/_compat.py +0 -0
  175. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/multi_files/__init__.py +0 -0
  176. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/pytorch/__init__.py +0 -0
  177. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/experimental/pytorch/_annloader.py +0 -0
  178. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/io.py +0 -0
  179. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/logging.py +0 -0
  180. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/tests/__init__.py +0 -0
  181. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/types.py +0 -0
  182. {anndata-0.12.6 → anndata-0.12.8}/src/anndata/typing.py +0 -0
  183. {anndata-0.12.6 → anndata-0.12.8}/src/testing/anndata/__init__.py +0 -0
  184. {anndata-0.12.6 → anndata-0.12.8}/src/testing/anndata/_doctest.py +0 -0
  185. {anndata-0.12.6 → anndata-0.12.8}/src/testing/anndata/py.typed +0 -0
  186. {anndata-0.12.6 → anndata-0.12.8}/tests/data/adata-comments.tsv +0 -0
  187. {anndata-0.12.6 → anndata-0.12.8}/tests/data/adata.csv +0 -0
  188. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/readme.md +0 -0
  189. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.11.4/adata.h5ad +0 -0
  190. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.11.4/adata.zarr.zip +0 -0
  191. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.11.4/readme.md +0 -0
  192. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.7.0/adata.h5ad +0 -0
  193. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.7.0/adata.zarr.zip +0 -0
  194. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.7.8/adata.h5ad +0 -0
  195. {anndata-0.12.6 → anndata-0.12.8}/tests/data/archives/v0.7.8/adata.zarr.zip +0 -0
  196. {anndata-0.12.6 → anndata-0.12.8}/tests/data/excel.xlsx +0 -0
  197. {anndata-0.12.6 → anndata-0.12.8}/tests/data/umi_tools.tsv.gz +0 -0
  198. {anndata-0.12.6 → anndata-0.12.8}/tests/lazy/test_write.py +0 -0
  199. {anndata-0.12.6 → anndata-0.12.8}/tests/test_anncollection.py +0 -0
  200. {anndata-0.12.6 → anndata-0.12.8}/tests/test_awkward.py +0 -0
  201. {anndata-0.12.6 → anndata-0.12.8}/tests/test_backed_dense.py +0 -0
  202. {anndata-0.12.6 → anndata-0.12.8}/tests/test_backed_hdf5.py +0 -0
  203. {anndata-0.12.6 → anndata-0.12.8}/tests/test_base.py +0 -0
  204. {anndata-0.12.6 → anndata-0.12.8}/tests/test_deprecations.py +0 -0
  205. {anndata-0.12.6 → anndata-0.12.8}/tests/test_extensions.py +0 -0
  206. {anndata-0.12.6 → anndata-0.12.8}/tests/test_get_vector.py +0 -0
  207. {anndata-0.12.6 → anndata-0.12.8}/tests/test_gpu.py +0 -0
  208. {anndata-0.12.6 → anndata-0.12.8}/tests/test_inplace_subset.py +0 -0
  209. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_conversion.py +0 -0
  210. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_dispatched.py +0 -0
  211. {anndata-0.12.6 → anndata-0.12.8}/tests/test_io_utils.py +0 -0
  212. {anndata-0.12.6 → anndata-0.12.8}/tests/test_obsmvarm.py +0 -0
  213. {anndata-0.12.6 → anndata-0.12.8}/tests/test_obspvarp.py +0 -0
  214. {anndata-0.12.6 → anndata-0.12.8}/tests/test_raw.py +0 -0
  215. {anndata-0.12.6 → anndata-0.12.8}/tests/test_repr.py +0 -0
  216. {anndata-0.12.6 → anndata-0.12.8}/tests/test_settings.py +0 -0
  217. {anndata-0.12.6 → anndata-0.12.8}/tests/test_structured_arrays.py +0 -0
  218. {anndata-0.12.6 → anndata-0.12.8}/tests/test_transpose.py +0 -0
  219. {anndata-0.12.6 → anndata-0.12.8}/tests/test_uns.py +0 -0
  220. {anndata-0.12.6 → anndata-0.12.8}/tests/test_x.py +0 -0
@@ -0,0 +1,43 @@
1
+ {
2
+ "template": "https://github.com/scverse/cookiecutter-scverse",
3
+ "commit": "d383d94fadff9e4e6fdb59d77c68cb900d7cedec",
4
+ "checkout": "v0.6.0",
5
+ "context": {
6
+ "cookiecutter": {
7
+ "project_name": "anndata",
8
+ "package_name": "anndata",
9
+ "project_description": "Annotated data.",
10
+ "author_full_name": "Philipp Angerer",
11
+ "author_email": "philipp.angerer@helmholtz-munich.de",
12
+ "github_user": "scverse",
13
+ "github_repo": "anndata",
14
+ "license": "BSD 3-Clause License",
15
+ "ide_integration": true,
16
+ "_copy_without_render": [
17
+ ".github/workflows/build.yaml",
18
+ ".github/workflows/test.yaml",
19
+ "docs/_templates/autosummary/**.rst"
20
+ ],
21
+ "_exclude_on_template_update": [
22
+ "CHANGELOG.md",
23
+ "LICENSE",
24
+ "README.md",
25
+ "docs/api.md",
26
+ "docs/index.md",
27
+ "docs/notebooks/example.ipynb",
28
+ "docs/references.bib",
29
+ "docs/references.md",
30
+ "src/**",
31
+ "tests/**"
32
+ ],
33
+ "_render_devdocs": false,
34
+ "_jinja2_env_vars": {
35
+ "lstrip_blocks": true,
36
+ "trim_blocks": true
37
+ },
38
+ "_template": "https://github.com/scverse/cookiecutter-scverse",
39
+ "_commit": "d383d94fadff9e4e6fdb59d77c68cb900d7cedec"
40
+ }
41
+ },
42
+ "directory": null
43
+ }
@@ -44,6 +44,8 @@ jobs:
44
44
  matrix:
45
45
  env: ${{ fromJSON(needs.get-environments.outputs.envs) }}
46
46
  io_mark: ["zarr_io", "not zarr_io", "dask_distributed"] # dask_distributed should not be run with -n auto as it uses a client with processes
47
+ permissions:
48
+ id-token: write # for codecov OIDC
47
49
  env: # environment variables for use in codecov’s env_vars tagging
48
50
  ENV_NAME: ${{ matrix.env.name }}
49
51
  IO_MARK: ${{ matrix.io_mark }}
@@ -64,34 +66,33 @@ jobs:
64
66
 
65
67
  - name: Install dependencies
66
68
  run: |
67
- # https://github.com/pallets/click/issues/3066
68
- uv tool install --with='click!=8.3.0' hatch
69
+ uv tool install hatch
69
70
  hatch -v env create ${{ matrix.env.name }}
70
71
 
71
72
  - name: Run tests
72
- env:
73
- COVERAGE_PROCESS_START: ${{ github.workspace }}/pyproject.toml
74
73
  run: |
75
74
  hatch run ${{ matrix.env.name }}:run-cov -v --color=yes ${{ matrix.io_mark != 'dask_distributed' && '-n auto' || '' }} --junitxml=test-data/test-results.xml -m "${{ matrix.io_mark }}" ${{ matrix.env.args }}
76
75
  hatch run ${{ matrix.env.name }}:cov-combine
77
76
  hatch run ${{ matrix.env.name }}:coverage xml
77
+ hatch run ${{ matrix.env.name }}:cov-report
78
78
 
79
79
  - name: Upload test results
80
80
  if: ${{ !cancelled() }}
81
- uses: codecov/test-results-action@v1
81
+ uses: codecov/codecov-action@v5
82
82
  with:
83
- token: ${{ secrets.CODECOV_TOKEN }}
83
+ report_type: test_results
84
84
  env_vars: ENV_NAME,IO_MARK
85
+ files: test-data/test-results.xml
86
+ use_oidc: true
85
87
  fail_ci_if_error: true
86
- file: test-data/test-results.xml
87
88
 
88
89
  - name: Upload coverage data
89
90
  uses: codecov/codecov-action@v5
90
91
  with:
91
- token: ${{ secrets.CODECOV_TOKEN }}
92
92
  env_vars: ENV_NAME,IO_MARK
93
- fail_ci_if_error: true
94
93
  files: test-data/coverage.xml
94
+ use_oidc: true
95
+ fail_ci_if_error: true
95
96
 
96
97
  build:
97
98
  runs-on: ubuntu-24.04
@@ -52,9 +52,10 @@ jobs:
52
52
  - name: Nvidia SMI sanity check
53
53
  run: nvidia-smi
54
54
 
55
- - name: Install yq
55
+ - name: Install yq # https://cirun.slack.com/archives/C09SNDRB3A8/p1766512487317849?thread_ts=1766512112.938459&cid=C09SNDRB3A8
56
56
  run: |
57
- sudo snap install yq
57
+ sudo wget -qO /usr/local/bin/yq https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64
58
+ sudo chmod +x /usr/local/bin/yq
58
59
 
59
60
  - name: Extract max Python version from classifiers
60
61
  run: |
@@ -1,6 +1,6 @@
1
1
  repos:
2
2
  - repo: https://github.com/astral-sh/ruff-pre-commit
3
- rev: v0.13.0
3
+ rev: v0.14.7
4
4
  hooks:
5
5
  - id: ruff-check
6
6
  args: ["--fix"]
@@ -10,7 +10,7 @@ repos:
10
10
  id: ruff
11
11
  args: ["--preview", "--select=PLR0917"]
12
12
  - repo: https://github.com/biomejs/pre-commit
13
- rev: v2.1.2
13
+ rev: v2.3.8
14
14
  hooks:
15
15
  - id: biome-format
16
16
  - repo: https://github.com/ComPWA/taplo-pre-commit
@@ -2,7 +2,7 @@ version: 2
2
2
  build:
3
3
  os: ubuntu-24.04
4
4
  tools:
5
- python: "3.13"
5
+ python: "3.14"
6
6
  jobs:
7
7
  post_checkout:
8
8
  # unshallow so version can be derived from tag
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: anndata
3
- Version: 0.12.6
3
+ Version: 0.12.8
4
4
  Summary: Annotated data.
5
5
  Project-URL: Documentation, https://anndata.readthedocs.io/
6
6
  Project-URL: Source, https://github.com/scverse/anndata
@@ -31,7 +31,7 @@ Requires-Dist: legacy-api-wrap
31
31
  Requires-Dist: natsort
32
32
  Requires-Dist: numpy>=1.26
33
33
  Requires-Dist: packaging>=24.2
34
- Requires-Dist: pandas!=2.1.2,>=2.1.0
34
+ Requires-Dist: pandas!=2.1.2,<3,>=2.1.0
35
35
  Requires-Dist: scipy>=1.12
36
36
  Requires-Dist: zarr!=3.0.*,>=2.18.7
37
37
  Provides-Extra: cu11
@@ -57,7 +57,7 @@ Requires-Dist: sphinx-copybutton; extra == 'doc'
57
57
  Requires-Dist: sphinx-design>=0.5.0; extra == 'doc'
58
58
  Requires-Dist: sphinx-issues>=5.0.1; extra == 'doc'
59
59
  Requires-Dist: sphinx-toolbox>=3.8.0; extra == 'doc'
60
- Requires-Dist: sphinx>=8.2.1; extra == 'doc'
60
+ Requires-Dist: sphinx<9,>=8.2.1; extra == 'doc'
61
61
  Requires-Dist: sphinxext-opengraph; extra == 'doc'
62
62
  Requires-Dist: towncrier>=24.8.0; extra == 'doc'
63
63
  Provides-Extra: gpu
@@ -74,18 +74,18 @@ Requires-Dist: boltons; extra == 'test'
74
74
  Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,!=2025.2.*,!=2025.3.*,!=2025.4.*,!=2025.5.*,!=2025.6.*,!=2025.7.*,!=2025.8.*,>=2023.5.1; extra == 'test'
75
75
  Requires-Dist: dask[distributed]; extra == 'test'
76
76
  Requires-Dist: filelock; extra == 'test'
77
- Requires-Dist: httpx<1.0; extra == 'test'
78
77
  Requires-Dist: joblib; extra == 'test'
79
78
  Requires-Dist: loompy>=3.0.5; extra == 'test'
80
79
  Requires-Dist: matplotlib; extra == 'test'
81
80
  Requires-Dist: openpyxl; extra == 'test'
81
+ Requires-Dist: pooch; extra == 'test'
82
82
  Requires-Dist: pyarrow; extra == 'test'
83
+ Requires-Dist: pytest; extra == 'test'
83
84
  Requires-Dist: pytest-cov; extra == 'test'
84
85
  Requires-Dist: pytest-memray; extra == 'test'
85
86
  Requires-Dist: pytest-mock; extra == 'test'
86
87
  Requires-Dist: pytest-randomly; extra == 'test'
87
88
  Requires-Dist: pytest-xdist[psutil]; extra == 'test'
88
- Requires-Dist: pytest<8.3.4,>=8.2; extra == 'test'
89
89
  Requires-Dist: requests; extra == 'test'
90
90
  Requires-Dist: scanpy>=1.10; extra == 'test'
91
91
  Requires-Dist: scikit-learn; extra == 'test'
@@ -96,18 +96,18 @@ Requires-Dist: boltons; extra == 'test-min'
96
96
  Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,!=2025.2.*,!=2025.3.*,!=2025.4.*,!=2025.5.*,!=2025.6.*,!=2025.7.*,!=2025.8.*,>=2023.5.1; extra == 'test-min'
97
97
  Requires-Dist: dask[distributed]; extra == 'test-min'
98
98
  Requires-Dist: filelock; extra == 'test-min'
99
- Requires-Dist: httpx<1.0; extra == 'test-min'
100
99
  Requires-Dist: joblib; extra == 'test-min'
101
100
  Requires-Dist: loompy>=3.0.5; extra == 'test-min'
102
101
  Requires-Dist: matplotlib; extra == 'test-min'
103
102
  Requires-Dist: openpyxl; extra == 'test-min'
103
+ Requires-Dist: pooch; extra == 'test-min'
104
104
  Requires-Dist: pyarrow; extra == 'test-min'
105
+ Requires-Dist: pytest; extra == 'test-min'
105
106
  Requires-Dist: pytest-cov; extra == 'test-min'
106
107
  Requires-Dist: pytest-memray; extra == 'test-min'
107
108
  Requires-Dist: pytest-mock; extra == 'test-min'
108
109
  Requires-Dist: pytest-randomly; extra == 'test-min'
109
110
  Requires-Dist: pytest-xdist[psutil]; extra == 'test-min'
110
- Requires-Dist: pytest<8.3.4,>=8.2; extra == 'test-min'
111
111
  Requires-Dist: scanpy>=1.10; extra == 'test-min'
112
112
  Requires-Dist: scikit-learn; extra == 'test-min'
113
113
  Description-Content-Type: text/markdown
@@ -18,11 +18,11 @@ class Dataset2D:
18
18
  params = (
19
19
  ("zarr", "h5ad"),
20
20
  ((-1,), None),
21
- ("cat", "numeric", "string-array", "nullable-string-array"),
21
+ ("cat", "numeric", "string-array", "nullable-string-array", "all"),
22
22
  )
23
23
 
24
24
  def setup_cache(self):
25
- n_obs = 10000
25
+ n_obs = 100_000
26
26
  array_types = {
27
27
  "numeric": np.arange(n_obs),
28
28
  "string-array": np.array(["a"] * n_obs),
@@ -40,17 +40,30 @@ class Dataset2D:
40
40
  if writing_string_array_on_disk := (
41
41
  isinstance(v, np.ndarray) and df["a"].dtype == "string"
42
42
  ):
43
- df["a"] = df["a"].to_numpy()
43
+ with pd.option_context("future.infer_string", False): # noqa: FBT003
44
+ df["a"] = df["a"].to_numpy()
44
45
  with ad.settings.override(allow_write_nullable_strings=True):
45
46
  ad.io.write_elem(store, "df", df)
46
47
  if writing_string_array_on_disk:
47
48
  assert store["df"]["a"].attrs["encoding-type"] == "string-array"
49
+ for store in [
50
+ h5py.File("data_all.h5ad", mode="w"),
51
+ zarr.open("data_all.zarr", mode="w", zarr_version=2),
52
+ ]:
53
+ df = pd.DataFrame(array_types, index=[f"cell{i}" for i in range(n_obs)])
54
+ # write a string array by triggering:
55
+ # https://github.com/scverse/anndata/blob/71966500949adcac4e49d2233f06e9f11f438e19/src/anndata/_io/specs/methods.py#L557-L559
56
+ df["string-array"] = df["string-array"].to_numpy().astype(object)
57
+ with ad.settings.override(allow_write_nullable_strings=True):
58
+ ad.io.write_elem(store, "df", df)
48
59
 
49
60
  def setup(
50
61
  self,
51
62
  store_type: Literal["zarr", "h5ad"],
52
63
  chunks: None | tuple[int],
53
- array_type: Literal["cat", "numeric", "string-array", "nullable-string-array"],
64
+ array_type: Literal[
65
+ "cat", "numeric", "string-array", "nullable-string-array", "all"
66
+ ],
54
67
  ):
55
68
  self.store = (
56
69
  h5py.File(f"data_{array_type}.h5ad", mode="r")
@@ -1,10 +1,9 @@
1
1
  .. sidebar:: Key Contributors
2
2
 
3
- * `Isaac Virshup`_: anndata >= 0.7, diverse contributions
3
+ * Isaac Virshup: anndata >= 0.7, diverse contributions
4
4
  * Sergei Rybakov: diverse contributions
5
- * `Alex Wolf`_: initial conception/development
5
+ * Alex Wolf: initial conception/development
6
6
  * Philipp Angerer: initial conception/development, software quality
7
+ * Ilan Gold: improved cloud support, software quality
7
8
 
8
9
  .. _contributions graph: https://github.com/scverse/anndata/graphs/contributors
9
- .. _Isaac Virshup: https://twitter.com/ivirshup
10
- .. _Alex Wolf: https://twitter.com/falexwolf
@@ -22,14 +22,14 @@ Let's start off with an example:
22
22
  >>> from scipy import sparse
23
23
  >>> from anndata import AnnData
24
24
  >>> pbmc = sc.datasets.pbmc68k_reduced()
25
- >>> pbmc
25
+ >>> pbmc # doctest: +ELLIPSIS
26
26
  AnnData object with n_obs × n_vars = 700 × 765
27
27
  obs: 'bulk_labels', 'n_genes', 'percent_mito', 'n_counts', 'S_score', 'G2M_score', 'phase', 'louvain'
28
28
  var: 'n_counts', 'means', 'dispersions', 'dispersions_norm', 'highly_variable'
29
29
  uns: 'bulk_labels_colors', 'louvain', 'louvain_colors', 'neighbors', 'pca', 'rank_genes_groups'
30
30
  obsm: 'X_pca', 'X_umap'
31
31
  varm: 'PCs'
32
- obsp: 'distances', 'connectivities'
32
+ obsp: ...
33
33
 
34
34
  If we split this object up by clusters of observations, then stack those subsets we'll obtain the same values – just ordered differently.
35
35
 
@@ -85,11 +85,13 @@ napoleon_use_rtype = True # having a separate entry generally helps readability
85
85
  napoleon_use_param = True
86
86
  napoleon_custom_sections = [("Params", "Parameters")]
87
87
  typehints_defaults = "braces"
88
+ always_use_bars_union = True # use `|`, not `Union` in types even when on Python ≤3.14
88
89
  todo_include_todos = False
89
90
  nitpicky = True # Report broken links
90
91
  nitpick_ignore = [ # APIs without an intersphinx entry
91
- # This API isn’t actually documented
92
+ # These APIs aren’t actually documented
92
93
  ("py:class", "anndata._core.raw.Raw"),
94
+ ("py:class", "pandas._libs.missing.NAType"),
93
95
  # TODO: remove zappy support; the zappy repo is archived
94
96
  ("py:class", "anndata.compat.ZappyArray"),
95
97
  ]
@@ -132,10 +134,8 @@ intersphinx_mapping = dict(
132
134
  loompy=("https://linnarssonlab.org/loompy", None),
133
135
  numpy=("https://numpy.org/doc/stable", None),
134
136
  obstore=("https://developmentseed.org/obstore/latest/", None),
135
- pandas=("https://pandas.pydata.org/pandas-docs/stable", None),
136
- # TODO: switch to `/3` once docs are built with Python 3.14
137
- # https://github.com/readthedocs/readthedocs.org/issues/12523
138
- python=("https://docs.python.org/3.13", None),
137
+ pandas=("https://pandas.pydata.org/pandas-docs/version/2.3", None),
138
+ python=("https://docs.python.org/3", None),
139
139
  scipy=("https://docs.scipy.org/doc/scipy", None),
140
140
  sklearn=("https://scikit-learn.org/stable", None),
141
141
  xarray=("https://docs.xarray.dev/en/stable", None),
@@ -170,8 +170,10 @@ qualname_overrides = {
170
170
  "anndata.compat.XDataset": "xarray.Dataset",
171
171
  "awkward.highlevel.Array": "ak.Array",
172
172
  "numpy.int64": ("py:attr", "numpy.int64"),
173
+ "numpy.dtypes.StringDType": ("py:attr", "numpy.dtypes.StringDType"),
173
174
  "pandas.DataFrame.iloc": ("py:attr", "pandas.DataFrame.iloc"),
174
175
  "pandas.DataFrame.loc": ("py:attr", "pandas.DataFrame.loc"),
176
+ "pandas.core.dtypes.dtypes.BaseMaskedDtype": "pandas.api.extensions.ExtensionDtype",
175
177
  # should be fixed soon: https://github.com/tox-dev/sphinx-autodoc-typehints/pull/516
176
178
  "types.EllipsisType": ("py:data", "types.EllipsisType"),
177
179
  "pathlib._local.Path": "pathlib.Path",
@@ -7,12 +7,13 @@ but will still be read by newer versions of the library.
7
7
  ```
8
8
 
9
9
  AnnData objects are saved on disk to hierarchical array stores like [HDF5]
10
- (via {doc}`H5py <h5py:index>`) and {doc}`zarr:index`.
10
+ (via {doc}`H5py <h5py:index>`) and {mod}`zarr`.
11
11
  This allows us to have very similar structures in disk and on memory.
12
12
 
13
13
  As an example we’ll look into a typical `.h5ad`/ `.zarr` object that’s been through an analysis.
14
14
  The structures are largely equivalent, though there are a few minor differences when it comes to type encoding.
15
15
 
16
+ (elements)=
16
17
  ## Elements
17
18
 
18
19
  <!-- I’ve started using h5py since I couldn’t figure out a nice way to print attributes from bash. -->
@@ -69,12 +70,14 @@ For example, we can see that this file represents an `AnnData` object from its m
69
70
 
70
71
  Using this information, we're able to dispatch onto readers for the different element types that you'd find in an anndata.
71
72
 
73
+ (element)=
72
74
  ### Element Specification
73
75
 
74
76
  * An element can be any object within the storage hierarchy (typically an array or group) with associated metadata
75
77
  * An element MUST have a string-valued field `"encoding-type"` in its metadata
76
78
  * An element MUST have a string-valued field `"encoding-version"` in its metadata that can be evaluated to a version
77
79
 
80
+ (anndata)=
78
81
  ### AnnData specification (v0.1.0)
79
82
 
80
83
  * An `AnnData` object MUST be a group.
@@ -88,10 +91,11 @@ Using this information, we're able to dispatch onto readers for the different el
88
91
  * The group MAY contain a mapping `varp`. Entries in `varp` MUST be sparse or dense arrays. The entries first two dimensions MUST be of size `n_var`
89
92
  * The group MAY contain a mapping `uns`. Entries in `uns` MUST be an anndata encoded type.
90
93
 
94
+ (dense-arrays)=
91
95
  ## Dense arrays
92
96
 
93
97
  Dense numeric arrays have the most simple representation on disk,
94
- as they have native equivalents in H5py {doc}`h5py:high/dataset` and Zarr {doc}`Arrays <zarr:user-guide/arrays>`.
98
+ as they have native equivalents in H5py {doc}`h5py:high/dataset` and {class}`zarr.Array`\ s.
95
99
  We can see an example of this with dimensionality reductions stored in the `obsm` group:
96
100
 
97
101
  `````{tab-set}
@@ -129,11 +133,13 @@ X_pca Dataset {38410, 50}
129
133
  X_umap Dataset {38410, 2}
130
134
  ``` -->
131
135
 
136
+ (array)=
132
137
  ### Dense arrays specification (v0.2.0)
133
138
 
134
139
  * Dense arrays MUST be stored in an Array object
135
140
  * Dense arrays MUST have the entries `'encoding-type': 'array'` and `'encoding-version': '0.2.0'` in their metadata
136
141
 
142
+ (sparse-arrays)=
137
143
  ## Sparse arrays
138
144
 
139
145
  Sparse arrays don’t have a native representations in HDF5 or Zarr,
@@ -188,6 +194,8 @@ indptr <zarr.core.Array '/X/indptr' (164115,) int32 read-only>
188
194
 
189
195
  `````
190
196
 
197
+ (csr_matrix)=
198
+ (csc_matrix)=
191
199
  ### Sparse array specification (v0.1.0)
192
200
 
193
201
  * Each sparse array MUST be its own group
@@ -197,6 +205,7 @@ indptr <zarr.core.Array '/X/indptr' (164115,) int32 read-only>
197
205
  * `"encoding-version"`, which is set to `"0.1.0"`
198
206
  * `"shape"` which is an integer array of length 2 whose values are the sizes of the array's dimensions
199
207
 
208
+ (dataframes)=
200
209
  ## DataFrames
201
210
 
202
211
  DataFrames are saved as a columnar format in a group, so each column of a DataFrame is saved as a separate array.
@@ -263,6 +272,7 @@ feature_is_filtered <zarr.core.Array '/var/feature_is_filtered' (40145,) bool re
263
272
  {'encoding-type': 'array', 'encoding-version': '0.2.0'}
264
273
  ```
265
274
 
275
+ (dataframe)=
266
276
  ### Dataframe Specification (v0.2.0)
267
277
 
268
278
  * A dataframe MUST be stored as a group
@@ -274,6 +284,7 @@ feature_is_filtered <zarr.core.Array '/var/feature_is_filtered' (40145,) bool re
274
284
  * Each entry in the group MUST correspond to an array with equivalent first dimensions
275
285
  * Each entry SHOULD share chunk sizes (in the HDF5 or zarr container)
276
286
 
287
+ (mappings)=
277
288
  ## Mappings
278
289
 
279
290
  Mappings are simply stored as `Group`s on disk.
@@ -314,13 +325,14 @@ pca/variance_ratio <zarr.core.Array '/uns/pca/variance_ratio' (50,) float64 read
314
325
 
315
326
  `````
316
327
 
317
-
318
-
328
+ (dict)=
329
+ (mapping)=
319
330
  ### Mapping specifications (v0.1.0)
320
331
 
321
332
  * Each mapping MUST be its own group
322
333
  * The group's metadata MUST contain the encoding metadata `"encoding-type": "dict"`, `"encoding-version": "0.1.0"`
323
334
 
335
+ (scalars)=
324
336
  ## Scalars
325
337
 
326
338
  Zero dimensional arrays are used for scalar values (i.e. single values like strings, numbers or booleans).
@@ -363,6 +375,8 @@ random_state <zarr.core.Array '/uns/neighbors/params/random_state' () int64 read
363
375
  {'encoding-type': 'string', 'encoding-version': '0.2.0'}
364
376
  ```
365
377
 
378
+ (numeric-scalar)=
379
+ (string)=
366
380
  ### Scalar specification (v0.2.0)
367
381
 
368
382
  * Scalars MUST be written as a 0 dimensional array
@@ -374,6 +388,7 @@ random_state <zarr.core.Array '/uns/neighbors/params/random_state' () int64 read
374
388
  * In zarr, scalar strings MUST be stored as a fixed length unicode dtype
375
389
  * In HDF5, scalar strings MUST be stored as a variable length utf-8 encoded string dtype
376
390
 
391
+ (categorical-arrays)=
377
392
  ## Categorical arrays
378
393
 
379
394
  ```python
@@ -414,6 +429,7 @@ codes <zarr.core.Array '/obs/development_stage/codes' (164114,) int8 read-only>
414
429
 
415
430
  `````
416
431
 
432
+ (categorical)=
417
433
  ### Categorical array specification (v0.2.0)
418
434
 
419
435
  * Categorical arrays MUST be stored as a group
@@ -423,6 +439,7 @@ codes <zarr.core.Array '/obs/development_stage/codes' (164114,) int8 read-only>
423
439
  * The `"codes"` array MAY contain signed integer values. If so, the code `-1` denotes a missing value
424
440
  * The group MUST contain an array called `"categories"`
425
441
 
442
+ (string-arrays)=
426
443
  ## String arrays
427
444
 
428
445
  Arrays of strings are handled differently than numeric arrays since numpy doesn't really have a good way of representing arrays of unicode strings.
@@ -457,6 +474,7 @@ Arrays of strings are handled differently than numeric arrays since numpy doesn'
457
474
  {'encoding-type': 'string-array', 'encoding-version': '0.2.0'}
458
475
  ```
459
476
 
477
+ (string-array)=
460
478
  ### String array specifications (v0.2.0)
461
479
 
462
480
  * String arrays MUST be stored in arrays
@@ -464,9 +482,10 @@ Arrays of strings are handled differently than numeric arrays since numpy doesn'
464
482
  * In `zarr`, string arrays MUST be stored using `numcodecs`' `VLenUTF8` codec
465
483
  * In `HDF5`, string arrays MUST be stored using the variable length string data type, with a utf-8 encoding
466
484
 
467
- ## Nullable integers and booleans
485
+ (nullable-arrays)=
486
+ ## Nullable integers, booleans, and strings
468
487
 
469
- We support IO with Pandas nullable integer and boolean arrays.
488
+ We support IO with Pandas nullable integer, boolean, and string arrays.
470
489
  We represent these on disk similar to `numpy` masked arrays, `julia` nullable arrays, or `arrow` validity bitmaps (see {issue}`504` for more discussion).
471
490
  That is, we store an indicator array (or mask) of null values alongside the array of all values.
472
491
 
@@ -523,21 +542,33 @@ nullable_integer/values <zarr.core.Array '/nullable_integer/values' (4,) int64>
523
542
  {'encoding-type': 'nullable-integer', 'encoding-version': '0.1.0'}
524
543
  ```
525
544
 
545
+ (nullable-integer)=
526
546
  ### Nullable integer specifications (v0.1.0)
527
547
 
528
548
  * Nullable integers MUST be stored as a group
529
- * The group's attributes MUST have contain the encoding metadata `"encoding-type": "nullable-integer"`, `"encoding-version": "0.1.0"`
549
+ * The groups attributes MUST contain the encoding metadata `"encoding-type": "nullable-integer"`, `"encoding-version": "0.1.0"`
530
550
  * The group MUST contain an integer valued array under the key `"values"`
531
551
  * The group MUST contain an boolean valued array under the key `"mask"`
532
552
 
553
+ (nullable-boolean)=
533
554
  ### Nullable boolean specifications (v0.1.0)
534
555
 
535
556
  * Nullable booleans MUST be stored as a group
536
- * The group's attributes MUST have contain the encoding metadata `"encoding-type": "nullable-boolean"`, `"encoding-version": "0.1.0"`
557
+ * The groups attributes MUST contain the encoding metadata `"encoding-type": "nullable-boolean"`, `"encoding-version": "0.1.0"`
537
558
  * The group MUST contain an boolean valued array under the key `"values"`
538
559
  * The group MUST contain an boolean valued array under the key `"mask"`
539
560
  * The `"values"` and `"mask"` arrays MUST be the same shape
540
561
 
562
+ (nullable-string-array)=
563
+ ### Nullable string specifications (v0.1.0)
564
+
565
+ * Nullable strings MUST be stored as a group
566
+ * The group’s attributes MUST contain the encoding metadata `"encoding-type": "nullable-string-array"`, `"encoding-version": "0.1.0"`
567
+ * The group MUST contain a string valued array under the key `"values"`
568
+ * The group MUST contain a boolean valued array under the key `"mask"`
569
+ * The `"values"` and `"mask"` arrays MUST be the same shape
570
+
571
+ (awkward-array)=
541
572
  ## AwkwardArrays
542
573
 
543
574
  ```{warning}
@@ -0,0 +1,21 @@
1
+ ```{include} ../README.md
2
+ ```
3
+
4
+ # Latest additions
5
+
6
+ See {doc}`/release-notes/index`.
7
+
8
+ ```{toctree}
9
+ :hidden: true
10
+ :maxdepth: 1
11
+
12
+ tutorials/index
13
+ api
14
+ concatenation
15
+ fileformat-prose
16
+ interoperability
17
+ benchmarks
18
+ contributing
19
+ release-notes/index
20
+ references
21
+ ```
@@ -1,11 +1,6 @@
1
1
  References
2
2
  ----------
3
3
 
4
- .. [Bredikhin22]
5
- Bredikhin *et al.* (2022),
6
- *MUON: multimodal omics analysis framework*,
7
- Genome Biology https://doi.org/10.1186/s13059-021-02577-8.
8
-
9
4
  .. [Hastie09]
10
5
  Hastie *et al.* (2009),
11
6
  *The Elements of Statistical Learning*,
@@ -0,0 +1,12 @@
1
+ (v0.12.7)=
2
+ ### 0.12.7 {small}`2025-12-16`
3
+
4
+ #### Documentation
5
+
6
+ - Add cruft config & update contributors {smaller}`zethson` ({pr}`2223`)
7
+
8
+ #### Bug fixes
9
+
10
+ - Handle `pandas.options.future.infer_string` {smaller}`P Angerer` {smaller}`I Gold` ({pr}`2133`)
11
+ - Ensure there are no dangling file handles in {func}`anndata.experimental.concat_on_disk` when passing `.h5ad`-terminated strings as path inputs. {user}`ilan-gold` ({pr}`2218`)
12
+ - Ensure {attr}`anndata.experimental.backed.Dataset2D.true_index` is carried over when subsetting by columns i.,e `ds[[col1, col2]]` {user}`ilan-gold` ({pr}`2220`)
@@ -0,0 +1,10 @@
1
+ (v0.12.8)=
2
+ ### 0.12.8 {small}`2026-01-27`
3
+
4
+ #### Bug fixes
5
+
6
+ - Actually copy single zarr store input in {func}`anndata.experimental.concat_on_disk` {user}`ilan-gold` ({pr}`2267`)
7
+ - Fix `compressor` kwarg handling when writing to zarr v3 {user}`ilan-gold` ({pr}`2270`)
8
+ - Only open HDF5 file once in backed mode {user}`flying-sheep` ({pr}`2274`)
9
+ - Fix {obj}`numpy.uint` support in {func}`anndata.experimental.read_lazy` and {func}`anndata.experimental.read_elem_lazy` {user}`flying-sheep` ({pr}`2287`)
10
+ - `var` index is loaded into memory if it wasn't previously for {func}`anndata.concat` when {attr}`anndata.AnnData.var` is a {class}`anndata.experimental.backed.Dataset2D` {user}`ilan-gold` ({pr}`2299`)
@@ -6,7 +6,11 @@ Here is a quick guide on some of our learnings so far:
6
6
 
7
7
  ## Consolidated Metadata
8
8
 
9
- All `zarr` stores are now consolidated by default when written via {func}`anndata.io.write_zarr` or {meth}`anndata.AnnData.write_zarr`. For more information on this topic, please seee {ref}`the zarr docs <zarr:user-guide-consolidated-metadata>`. Practcally, this changes means that once a store has been written, it should be treated as immutable **unless you remove the consolidated metadata and/or rewrite after the mutating operation** i.e., if you wish to use `anndata.io.write_elem` to add a column to `obs`, a `layer` etc. to an existing store. For example, to mutate an existing store on-disk, you may do:
9
+ All `zarr` stores are now consolidated by default when written via {func}`anndata.io.write_zarr` or {meth}`anndata.AnnData.write_zarr`.
10
+ For more information on this topic, please see the zarr [consolidated metadata] user guide.
11
+ Practcally, this changes means that once a store has been written, it should be treated as immutable **unless you remove the consolidated metadata and/or rewrite after the mutating operation** i.e.,
12
+ if you wish to use {func}`anndata.io.write_elem` to add a column to `obs`, a `layer` etc. to an existing store.
13
+ For example, to mutate an existing store on-disk, you may do:
10
14
 
11
15
  ```python
12
16
  g = zarr.open_group(orig_path, mode="a", use_consolidated=False)
@@ -19,13 +23,14 @@ ad.io.write_elem(
19
23
  zarr.consolidate_metadata(g.store)
20
24
  ```
21
25
 
22
- In this example, the store was opened unconsolidated (trying to open it as a consolidated store would error out), edited, and then reconsolidated. Alternatively, one could simple delete the file containing the consolidated metadata first at the root, `.zmetadata`.
26
+ In this example, the store was opened unconsolidated (trying to open it as a consolidated store would error out), edited, and then reconsolidated.
27
+ Alternatively, one could simple delete the file containing the consolidated metadata first at the root, `.zmetadata`.
23
28
 
24
29
  ## Remote data
25
30
 
26
31
  We now provide the {func}`anndata.experimental.read_lazy` feature for reading as much of the {class}`~anndata.AnnData` object as lazily as possible, using `dask` and {mod}`xarray`.
27
32
  Please note that this feature is experimental and subject to change.
28
- To enable this functionality in a performant and feature-complete way for remote data sources, we use {doc}`zarr:user-guide/consolidated_metadata` on the `zarr` store (written by default).
33
+ To enable this functionality in a performant and feature-complete way for remote data sources, we use [consolidated metadata] on the `zarr` store (written by default).
29
34
  Please note that this introduces consistency issues – if you update the structure of the underlying `zarr` store i.e., remove a column from `obs`, the consolidated metadata will no longer be valid.
30
35
  Further, note that without consolidated metadata, we cannot guarantee your stored `AnnData` object will be fully readable.
31
36
  And even if it is fully readable, it will almost certainly be much slower to read.
@@ -37,7 +42,7 @@ There are two ways of opening remote `zarr` stores from the `zarr-python` packag
37
42
 
38
43
  Local data generally poses a different set of challenges.
39
44
  First, write speeds can be somewhat slow and second, the creation of many small files on a file system can slow down a filesystem.
40
- For the "many small files" problem, `zarr` has introduced {ref}`sharding <zarr:user-guide-sharding>` in the v3 file format.
45
+ For the "many small files" problem, `zarr` has introduced [sharding] in the v3 file format.
41
46
  We offer {attr}`anndata.settings.auto_shard_zarr_v3` to hook into zarr's ability to automatically compute shards, which is experimental at the moment.
42
47
  Manual sharding requires knowledge of the array element you are writing (such as shape or data type), though, and therefore you will need to use {func}`anndata.experimental.write_dispatched` to use custom sharding.
43
48
  For example, you cannot shard a 1D array with `shard` sizes `(256, 256)`.
@@ -97,11 +102,13 @@ Therefore, we recommend passing in the {class}`zarr.codecs.BloscCodec` to `compr
97
102
 
98
103
  ## Dask
99
104
 
100
- Zarr v3 should be compatible with dask, although the default behavior is to use zarr's chunking for dask's own. With sharding, this behavior may be undesirable as shards can often contain many small chunks, thereby slowing down i/o as dask will need to index into the zarr store for every chunk. Therefore it may be better to customize this behavior by passing `chunks=my_zarr_array.shards` as an argument to {func}`dask.array.from_zarr` or similar.
105
+ Zarr v3 should be compatible with dask, although the default behavior is to use zarr's chunking for dask's own.
106
+ With sharding, this behavior may be undesirable as shards can often contain many small chunks, thereby slowing down i/o as dask will need to index into the zarr store for every chunk.
107
+ Therefore it may be better to customize this behavior by passing `chunks=my_zarr_array.shards` as an argument to {func}`dask.array.from_zarr` or similar.
101
108
 
102
109
  ## GPU i/o
103
110
 
104
- At the moment, it is unlikely your `anndata` i/o will work if you use {ref}`zarr.config.enable_gpu <zarr:user-guide-gpu>`.
111
+ At the moment, it is unlikely your `anndata` i/o will work if you use [`zarr.config.enable_gpu`][GPU user guide].
105
112
  It's *possible* dense data i/o i.e., using {func}`anndata.io.read_elem` will work as expected, but this functionality is untested – sparse data, awkward arrays, and dataframes will not.
106
113
  `kvikio` currently provides a {class}`kvikio.zarr.GDSStore` although there are no working compressors at the moment exported from the `zarr-python` package (work is underway for `Zstd`: {pr}`zarr-developers/zarr-python#2863`.
107
114
 
@@ -114,5 +121,8 @@ However, `zarr-python` has a fully `async` API and provides its own event-loop s
114
121
  We anticipate providing `async` versions of {func}`anndata.io.read_elem` and {func}`anndata.experimental.read_dispatched` so that users can download data asynchronously without using the `zarr-python` event loop.
115
122
  We also would like to create an asynchronous partial reader to enable iterative streaming of a dataset.
116
123
 
124
+ [consolidated metadata]: https://zarr.readthedocs.io/en/latest/user-guide/consolidated_metadata/
117
125
  [`obstore` claims]: https://developmentseed.org/obstore/latest/performance
126
+ [sharding]: https://zarr.readthedocs.io/en/stable/user-guide/arrays/#sharding
118
127
  [zarr-benchmarks]: https://github.com/LDeakin/zarr_benchmarks
128
+ [GPU user guide]: https://zarr.readthedocs.io/en/stable/user-guide/gpu/