anndata 0.12.0rc4__tar.gz → 0.12.2__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.
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/test-cpu.yml +6 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/.pre-commit-config.yaml +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/PKG-INFO +9 -10
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/asv.conf.json +2 -0
- anndata-0.12.2/benchmarks/benchmarks/dataset2d.py +61 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/benchmarks/sparse_dataset.py +18 -7
- {anndata-0.12.0rc4 → anndata-0.12.2}/biome.jsonc +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/conf.py +4 -3
- anndata-0.12.2/docs/release-notes/0.12.0.md +51 -0
- anndata-0.12.2/docs/release-notes/0.12.1.md +10 -0
- anndata-0.12.2/docs/release-notes/0.12.2.md +6 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/tutorials/zarr-v3.md +19 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/hatch.toml +1 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/pyproject.toml +13 -13
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/aligned_df.py +1 -1
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/anndata.py +23 -6
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/index.py +6 -13
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/merge.py +0 -6
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/raw.py +5 -3
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/sparse_dataset.py +5 -1
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/views.py +20 -14
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/xarray.py +20 -16
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/h5ad.py +48 -23
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/read.py +20 -5
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/specs/lazy_methods.py +25 -15
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/specs/methods.py +22 -20
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/specs/registry.py +15 -4
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/zarr.py +0 -20
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_settings.py +6 -3
- anndata-0.12.2/src/anndata/_settings.pyi +49 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/compat/__init__.py +36 -11
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/backed/_lazy_arrays.py +27 -5
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/tests/helpers.py +52 -50
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/utils.py +3 -4
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/testing/anndata/_pytest.py +4 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/conftest.py +15 -2
- anndata-0.12.2/tests/data/archives/v0.11.4/adata.h5ad +0 -0
- anndata-0.12.2/tests/data/archives/v0.11.4/adata.zarr.zip +0 -0
- anndata-0.12.2/tests/data/archives/v0.11.4/readme.md +10 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/lazy/conftest.py +12 -3
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/lazy/test_read.py +33 -3
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_awkward.py +2 -1
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_backed_hdf5.py +9 -6
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_backed_sparse.py +19 -15
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_base.py +4 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_concatenate_disk.py +12 -5
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_deprecations.py +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_backwards_compat.py +29 -6
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_dispatched.py +10 -5
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_elementwise.py +85 -27
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_partial.py +0 -6
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_warnings.py +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_readwrite.py +65 -11
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_settings.py +19 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_structured_arrays.py +24 -24
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_utils.py +4 -2
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_views.py +33 -15
- anndata-0.12.0rc4/docs/release-notes/0.12.0rc1.md +0 -26
- anndata-0.12.0rc4/docs/release-notes/0.12.0rc2.md +0 -14
- anndata-0.12.0rc4/docs/release-notes/0.12.0rc3.md +0 -6
- anndata-0.12.0rc4/docs/release-notes/0.12.0rc4.md +0 -15
- anndata-0.12.0rc4/docs/release-notes/2013.development.md +0 -1
- {anndata-0.12.0rc4 → anndata-0.12.2}/.cirun.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.codecov.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.editorconfig +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/ISSUE_TEMPLATE/enhancement-request.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/benchmark.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/check-pr-milestoned.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/close-stale.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/codespell.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/label-stale.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/publish.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.github/workflows/test-gpu.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.gitignore +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.gitmodules +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.prettierignore +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.prettierrc.yaml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.readthedocs.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.taplo.toml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.vscode/launch.json +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/.vscode/settings.json +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/LICENSE +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/README.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/README.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/benchmarks/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/benchmarks/anndata.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/benchmarks/readwrite.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/benchmarks/benchmarks/utils.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/ci/constraints.txt +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/ci/scripts/min-deps.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/ci/scripts/towncrier_automation.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/Makefile +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/_key_contributors.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/_static/img/anndata_schema.svg +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/_templates/autosummary/class.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/api.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/benchmark-read-write.ipynb +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/benchmarks.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/concatenation.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/contributing.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/extensions/autosummary_skip_inherited.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/extensions/no_skip_abc_members.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/extensions/patch_myst_cite.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/fileformat-prose.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/index.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/interoperability.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/news.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/references.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.1.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.3.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.4.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.5.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.6.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.7.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.8.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.10.9.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.11.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.11.1.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.11.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.11.3.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.11.4.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.4.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.5.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.6.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.6.x.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.3.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.4.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.5.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.6.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.7.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.7.8.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.8.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.9.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.9.1.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/0.9.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/release-notes/index.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/docs/tutorials/index.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/access.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/aligned_mapping.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/extensions.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/file_backing.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_core/storage.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/specs/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/utils.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_io/write.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_types.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_version.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/_warnings.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/abc.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/_dispatch_io.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/backed/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/backed/_compat.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/backed/_io.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/merge.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/multi_files/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/multi_files/_anncollection.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/pytorch/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/experimental/pytorch/_annloader.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/io.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/logging.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/tests/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/types.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/anndata/typing.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/testing/anndata/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/testing/anndata/_doctest.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/src/testing/anndata/py.typed +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/adata-comments.tsv +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/adata.csv +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/archives/readme.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/archives/v0.7.0/adata.h5ad +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/archives/v0.7.0/adata.zarr.zip +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/archives/v0.7.8/adata.h5ad +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/archives/v0.7.8/adata.zarr.zip +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/excel.xlsx +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/data/umi_tools.tsv.gz +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/lazy/test_concat.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/lazy/test_write.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_anncollection.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_annot.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_backed_dense.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_concatenate.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_dask.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_dask_view_mem.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_extensions.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_get_vector.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_gpu.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_helpers.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_inplace_subset.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_conversion.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_io_utils.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_layers.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_obsmvarm.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_obspvarp.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_raw.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_repr.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_transpose.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_uns.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_x.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.2}/tests/test_xarray.py +0 -0
|
@@ -38,7 +38,7 @@ jobs:
|
|
|
38
38
|
ENVS_JSON=$(NO_COLOR=1 uvx hatch env show --json | jq -c 'to_entries
|
|
39
39
|
| map(
|
|
40
40
|
select(.key | startswith("hatch-test"))
|
|
41
|
-
| { name: .key, python: .value.python }
|
|
41
|
+
| { name: .key, python: .value.python, args: (.value."extra-args" // [] | join(" ")) }
|
|
42
42
|
)')
|
|
43
43
|
echo "envs=${ENVS_JSON}" | tee $GITHUB_OUTPUT
|
|
44
44
|
test:
|
|
@@ -47,6 +47,7 @@ jobs:
|
|
|
47
47
|
strategy:
|
|
48
48
|
matrix:
|
|
49
49
|
env: ${{ fromJSON(needs.get-environments.outputs.envs) }}
|
|
50
|
+
io_mark: ["zarr_io", "not zarr_io"]
|
|
50
51
|
env: # environment variable for use in codecov’s env_vars tagging
|
|
51
52
|
ENV_NAME: ${{ matrix.env.name }}
|
|
52
53
|
steps:
|
|
@@ -55,6 +56,9 @@ jobs:
|
|
|
55
56
|
fetch-depth: 0
|
|
56
57
|
filter: blob:none
|
|
57
58
|
|
|
59
|
+
- name: Install system dependencies
|
|
60
|
+
run: sudo apt install -y hdf5-tools
|
|
61
|
+
|
|
58
62
|
- name: Set up Python ${{ matrix.env.python }}
|
|
59
63
|
uses: actions/setup-python@v5
|
|
60
64
|
with:
|
|
@@ -70,7 +74,7 @@ jobs:
|
|
|
70
74
|
run: uvx hatch -v env create ${{ matrix.env.name }}
|
|
71
75
|
|
|
72
76
|
- name: Run tests
|
|
73
|
-
run: uvx hatch run ${{ matrix.env.name }}:run-cov -v --color=yes -n auto --cov --cov-report=xml --junitxml=test-data/test-results.xml
|
|
77
|
+
run: uvx hatch run ${{ matrix.env.name }}:run-cov -v --color=yes -n auto --cov --cov-report=xml --junitxml=test-data/test-results.xml -m "${{ matrix.io_mark }}" ${{ matrix.env.args }}
|
|
74
78
|
|
|
75
79
|
- name: Upload coverage data
|
|
76
80
|
uses: codecov/codecov-action@v5
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
3
|
-
rev: v0.
|
|
3
|
+
rev: v0.12.4
|
|
4
4
|
hooks:
|
|
5
5
|
- id: ruff
|
|
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:
|
|
13
|
+
rev: v2.1.2
|
|
14
14
|
hooks:
|
|
15
15
|
- id: biome-format
|
|
16
16
|
- repo: https://github.com/ComPWA/taplo-pre-commit
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: anndata
|
|
3
|
-
Version: 0.12.
|
|
3
|
+
Version: 0.12.2
|
|
4
4
|
Summary: Annotated data.
|
|
5
5
|
Project-URL: Documentation, https://anndata.readthedocs.io/
|
|
6
6
|
Project-URL: Source, https://github.com/scverse/anndata
|
|
@@ -28,11 +28,11 @@ Requires-Dist: array-api-compat>=1.7.1
|
|
|
28
28
|
Requires-Dist: h5py>=3.8
|
|
29
29
|
Requires-Dist: legacy-api-wrap
|
|
30
30
|
Requires-Dist: natsort
|
|
31
|
-
Requires-Dist: numpy>=1.
|
|
31
|
+
Requires-Dist: numpy>=1.26
|
|
32
32
|
Requires-Dist: packaging>=24.2
|
|
33
|
-
Requires-Dist: pandas!=2.1.
|
|
34
|
-
Requires-Dist: scipy>=1.
|
|
35
|
-
Requires-Dist: zarr!=3.0
|
|
33
|
+
Requires-Dist: pandas!=2.1.2,>=2.1.0
|
|
34
|
+
Requires-Dist: scipy>=1.12
|
|
35
|
+
Requires-Dist: zarr!=3.0.*,>=2.18.7
|
|
36
36
|
Provides-Extra: cu11
|
|
37
37
|
Requires-Dist: cupy-cuda11x; extra == 'cu11'
|
|
38
38
|
Provides-Extra: cu12
|
|
@@ -74,13 +74,12 @@ Requires-Dist: boltons; extra == 'test'
|
|
|
74
74
|
Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'test'
|
|
75
75
|
Requires-Dist: dask[distributed]; extra == 'test'
|
|
76
76
|
Requires-Dist: filelock; extra == 'test'
|
|
77
|
-
Requires-Dist: httpx; extra == 'test'
|
|
77
|
+
Requires-Dist: httpx<1.0; extra == 'test'
|
|
78
78
|
Requires-Dist: joblib; extra == 'test'
|
|
79
79
|
Requires-Dist: loompy>=3.0.5; extra == 'test'
|
|
80
80
|
Requires-Dist: matplotlib; extra == 'test'
|
|
81
81
|
Requires-Dist: openpyxl; extra == 'test'
|
|
82
|
-
Requires-Dist:
|
|
83
|
-
Requires-Dist: pyarrow; extra == 'test'
|
|
82
|
+
Requires-Dist: pyarrow<21; extra == 'test'
|
|
84
83
|
Requires-Dist: pytest-cov; extra == 'test'
|
|
85
84
|
Requires-Dist: pytest-memray; extra == 'test'
|
|
86
85
|
Requires-Dist: pytest-mock; extra == 'test'
|
|
@@ -97,12 +96,12 @@ Requires-Dist: boltons; extra == 'test-min'
|
|
|
97
96
|
Requires-Dist: dask[array]!=2024.8.*,!=2024.9.*,<2025.2.0,>=2023.5.1; extra == 'test-min'
|
|
98
97
|
Requires-Dist: dask[distributed]; extra == 'test-min'
|
|
99
98
|
Requires-Dist: filelock; extra == 'test-min'
|
|
100
|
-
Requires-Dist: httpx; extra == 'test-min'
|
|
99
|
+
Requires-Dist: httpx<1.0; extra == 'test-min'
|
|
101
100
|
Requires-Dist: joblib; extra == 'test-min'
|
|
102
101
|
Requires-Dist: loompy>=3.0.5; extra == 'test-min'
|
|
103
102
|
Requires-Dist: matplotlib; extra == 'test-min'
|
|
104
103
|
Requires-Dist: openpyxl; extra == 'test-min'
|
|
105
|
-
Requires-Dist: pyarrow; extra == 'test-min'
|
|
104
|
+
Requires-Dist: pyarrow<21; extra == 'test-min'
|
|
106
105
|
Requires-Dist: pytest-cov; extra == 'test-min'
|
|
107
106
|
Requires-Dist: pytest-memray; extra == 'test-min'
|
|
108
107
|
Requires-Dist: pytest-mock; extra == 'test-min'
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import tempfile
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
import h5py
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import zarr
|
|
11
|
+
|
|
12
|
+
import anndata as ad
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import Callable
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Dataset2D:
|
|
19
|
+
param_names = ("gen_store", "chunks")
|
|
20
|
+
params = (
|
|
21
|
+
(
|
|
22
|
+
lambda: h5py.File(Path(tempfile.mkdtemp()) / "data.h5ad", mode="w"),
|
|
23
|
+
lambda: zarr.open(
|
|
24
|
+
Path(tempfile.mkdtemp()) / "data.zarr", mode="w", zarr_version=2
|
|
25
|
+
),
|
|
26
|
+
),
|
|
27
|
+
((-1,), None),
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
def setup(
|
|
31
|
+
self, gen_store: Callable[[], zarr.Group | h5py.File], chunks: None | tuple[int]
|
|
32
|
+
):
|
|
33
|
+
self.n_obs = 100000
|
|
34
|
+
df = pd.DataFrame(
|
|
35
|
+
{
|
|
36
|
+
"a": pd.Categorical(np.array(["a"] * self.n_obs)),
|
|
37
|
+
"b": np.arange(self.n_obs),
|
|
38
|
+
},
|
|
39
|
+
index=[f"cell{i}" for i in range(self.n_obs)],
|
|
40
|
+
)
|
|
41
|
+
store = gen_store()
|
|
42
|
+
ad.io.write_elem(store, "obs", df)
|
|
43
|
+
self.ds = ad.experimental.read_elem_lazy(store["obs"], chunks=chunks)
|
|
44
|
+
|
|
45
|
+
def time_getitem_slice(self, *_):
|
|
46
|
+
self.ds.iloc[0 : (self.n_obs // 2)].to_memory()
|
|
47
|
+
|
|
48
|
+
def peakmem_getitem_slice(self, *_):
|
|
49
|
+
self.ds.iloc[0 : (self.n_obs // 2)].to_memory()
|
|
50
|
+
|
|
51
|
+
def time_full_to_memory(self, *_):
|
|
52
|
+
self.ds.to_memory()
|
|
53
|
+
|
|
54
|
+
def peakmem_full_to_memory(self, *_):
|
|
55
|
+
self.ds.to_memory()
|
|
56
|
+
|
|
57
|
+
def time_getitem_bool_mask(self, *_):
|
|
58
|
+
self.ds.iloc[np.random.randint(0, self.n_obs, self.n_obs // 2)].to_memory()
|
|
59
|
+
|
|
60
|
+
def peakmem_getitem_bool_mask(self, *_):
|
|
61
|
+
self.ds.iloc[np.random.randint(0, self.n_obs, self.n_obs // 2)].to_memory()
|
|
@@ -4,11 +4,13 @@ from types import MappingProxyType
|
|
|
4
4
|
|
|
5
5
|
import numpy as np
|
|
6
6
|
import zarr
|
|
7
|
+
from dask.array.core import Array as DaskArray
|
|
7
8
|
from scipy import sparse
|
|
8
9
|
|
|
9
10
|
from anndata import AnnData
|
|
10
11
|
from anndata._core.sparse_dataset import sparse_dataset
|
|
11
12
|
from anndata._io.specs import write_elem
|
|
13
|
+
from anndata.experimental import read_elem_lazy
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
def make_alternating_mask(n):
|
|
@@ -37,27 +39,36 @@ class SparseCSRContiguousSlice:
|
|
|
37
39
|
# (10_000, 500)
|
|
38
40
|
],
|
|
39
41
|
_slices.keys(),
|
|
42
|
+
[True, False],
|
|
40
43
|
)
|
|
41
|
-
param_names = ("shape", "slice")
|
|
44
|
+
param_names = ("shape", "slice", "use_dask")
|
|
42
45
|
|
|
43
|
-
def setup(self, shape: tuple[int, int], slice: str):
|
|
46
|
+
def setup(self, shape: tuple[int, int], slice: str, use_dask: bool): # noqa: FBT001
|
|
44
47
|
X = sparse.random(
|
|
45
48
|
*shape, density=0.01, format="csr", random_state=np.random.default_rng(42)
|
|
46
49
|
)
|
|
47
50
|
self.slice = self._slices[slice]
|
|
48
51
|
g = zarr.group()
|
|
49
52
|
write_elem(g, "X", X)
|
|
50
|
-
self.x = sparse_dataset(g["X"])
|
|
53
|
+
self.x = read_elem_lazy(g["X"]) if use_dask else sparse_dataset(g["X"])
|
|
51
54
|
self.adata = AnnData(self.x)
|
|
52
55
|
|
|
53
56
|
def time_getitem(self, *_):
|
|
54
|
-
self.x[self.slice]
|
|
57
|
+
res = self.x[self.slice]
|
|
58
|
+
if isinstance(res, DaskArray):
|
|
59
|
+
res.compute()
|
|
55
60
|
|
|
56
61
|
def peakmem_getitem(self, *_):
|
|
57
|
-
self.x[self.slice]
|
|
62
|
+
res = self.x[self.slice]
|
|
63
|
+
if isinstance(res, DaskArray):
|
|
64
|
+
res.compute()
|
|
58
65
|
|
|
59
66
|
def time_getitem_adata(self, *_):
|
|
60
|
-
self.adata[self.slice]
|
|
67
|
+
res = self.adata[self.slice]
|
|
68
|
+
if isinstance(res, DaskArray):
|
|
69
|
+
res.compute()
|
|
61
70
|
|
|
62
71
|
def peakmem_getitem_adata(self, *_):
|
|
63
|
-
self.adata[self.slice]
|
|
72
|
+
res = self.adata[self.slice]
|
|
73
|
+
if isinstance(res, DaskArray):
|
|
74
|
+
res.compute()
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$schema": "https://biomejs.dev/schemas/1.
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.1.1/schema.json",
|
|
3
3
|
"formatter": { "useEditorconfig": true },
|
|
4
4
|
"overrides": [
|
|
5
5
|
{
|
|
6
|
-
"
|
|
6
|
+
"includes": ["./.vscode/*.json", "**/*.jsonc", "**/asv.conf.json"],
|
|
7
7
|
"json": {
|
|
8
8
|
"formatter": {
|
|
9
9
|
"trailingCommas": "all",
|
|
@@ -125,18 +125,19 @@ intersphinx_mapping = dict(
|
|
|
125
125
|
awkward=("https://awkward-array.org/doc/stable", None),
|
|
126
126
|
cupy=("https://docs.cupy.dev/en/stable", None),
|
|
127
127
|
dask=("https://docs.dask.org/en/stable", None),
|
|
128
|
+
fsspec=("https://filesystem-spec.readthedocs.io/en/stable/", None),
|
|
128
129
|
h5py=("https://docs.h5py.org/en/latest", None),
|
|
129
130
|
hdf5plugin=("https://hdf5plugin.readthedocs.io/en/latest", None),
|
|
131
|
+
kvikio=("https://docs.rapids.ai/api/kvikio/stable/", None),
|
|
130
132
|
loompy=("https://linnarssonlab.org/loompy", None),
|
|
131
133
|
numpy=("https://numpy.org/doc/stable", None),
|
|
134
|
+
obstore=("https://developmentseed.org/obstore/latest/", None),
|
|
132
135
|
pandas=("https://pandas.pydata.org/pandas-docs/stable", None),
|
|
133
136
|
python=("https://docs.python.org/3", None),
|
|
134
137
|
scipy=("https://docs.scipy.org/doc/scipy", None),
|
|
135
138
|
sklearn=("https://scikit-learn.org/stable", None),
|
|
136
|
-
zarr=("https://zarr.readthedocs.io/en/stable/", None),
|
|
137
139
|
xarray=("https://docs.xarray.dev/en/stable", None),
|
|
138
|
-
|
|
139
|
-
kvikio=("https://docs.rapids.ai/api/kvikio/stable/", None),
|
|
140
|
+
zarr=("https://zarr.readthedocs.io/en/stable/", None),
|
|
140
141
|
zarrs=("https://zarrs-python.readthedocs.io/en/stable/", None),
|
|
141
142
|
)
|
|
142
143
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
(v0.12.0)=
|
|
2
|
+
### 0.12.0 {small}`2025-07-16`
|
|
3
|
+
|
|
4
|
+
- (v0.12.0rc4)=
|
|
5
|
+
{guilabel}`rc4` 2025-06-18
|
|
6
|
+
- (v0.12.0rc3)=
|
|
7
|
+
{guilabel}`rc3` 2025-05-20
|
|
8
|
+
- (v0.12.0rc2)=
|
|
9
|
+
{guilabel}`rc2` 2025-05-15
|
|
10
|
+
- (v0.12.0rc1)=
|
|
11
|
+
{guilabel}`rc1` 2025-04-09
|
|
12
|
+
|
|
13
|
+
#### Breaking changes
|
|
14
|
+
|
|
15
|
+
- {guilabel}`rc1` Remove `anndata.read` {user}`ilan-gold` ({pr}`1766`)
|
|
16
|
+
- {guilabel}`rc1` Tighten usage of {class}`scipy.sparse.spmatrix` for describing sparse matrices in types and instance checks to only {class}`scipy.sparse.csr_matrix` and {class}`scipy.sparse.csc_matrix` {user}`ilan-gold` ({pr}`1768`)
|
|
17
|
+
- {guilabel}`rc1` Disallow declaration of {class}`~anndata.AnnData` with non-`cs{r,c}` sparse data-structures {user}`ilan-gold` ({pr}`1829`)
|
|
18
|
+
- {guilabel}`rc1` Upgrade all `DeprecationWarning`s to `FutureWarning`s {user}`ilan-gold` ({pr}`1874`)
|
|
19
|
+
- {guilabel}`rc4` Lower bound `xarray` by `2025.06.01`. {class}`pandas.arrays.StringArray` was previously used as the in-memory `nullable-string-array` container in `xarray`, but due to {issue}`pydata/xarray#10419` now uses {class}`numpy.ndarray` with an object data type. {user}`ilan-gold` ({pr}`2008`)
|
|
20
|
+
|
|
21
|
+
#### Bug fixes
|
|
22
|
+
|
|
23
|
+
- Fix {func}`anndata.experimental.backed.Dataset2D.reindex` internal setting {user}`ilan-gold` ({pr}`2018`)
|
|
24
|
+
- {guilabel}`rc1` Disallow writing of {class}`~anndata.experimental.backed.Dataset2D` objects {user}`ilan-gold` ({pr}`1887`)
|
|
25
|
+
- {guilabel}`rc1` Upgrade old deprecation warning to a `FutureWarning` on `BaseCompressedSparseDataset.__setitem__`, showing our intent to remove the feature in the next release. {user}`ilan-gold` ({pr}`1928`)
|
|
26
|
+
- {guilabel}`rc1` Don't use {func}`asyncio.run` internally for any operations {user}`ilan-gold` ({pr}`1933`)
|
|
27
|
+
- {guilabel}`rc1` Disallow forward slashes in keys for writing {user}`ilan-gold` ({pr}`1940`)
|
|
28
|
+
- {guilabel}`rc2` Convert 1d {class}`numpy.ndarray` and {class}`cupy.ndarray`s in {attr}`anndata.AnnData.obsm` and {attr}`anndata.AnnData.varm` to 2d {user}`ilan-gold` ({pr}`1962`)
|
|
29
|
+
- {guilabel}`rc3` Update zarr v3 bound to >3.0.8 to prevent corrupted data {issue}`zarr-developers/zarr-python#3061` {user}`ilan-gold` ({pr}`1993`)
|
|
30
|
+
|
|
31
|
+
#### Features
|
|
32
|
+
|
|
33
|
+
- {guilabel}`rc1` {data}`None` values can now be serialized to `.h5ad` and `.zarr`,
|
|
34
|
+
preserving e.g. {attr}`~anndata.AnnData.uns` structure through saving and loading {user}`flying-sheep` ({pr}`999`)
|
|
35
|
+
- {guilabel}`rc1` Add {func}`~anndata.experimental.read_elem_lazy` (in place of `read_elem_as_dask`) to handle backed dataframes, sparse arrays, and dense arrays, as well as a {func}`~anndata.experimental.read_lazy` to handle reading in as much of the on-disk data as possible to produce a {class}`~anndata.AnnData` object {user}`ilan-gold` ({pr}`1247`)
|
|
36
|
+
- {guilabel}`rc1` Support {mod}`zarr` version 3 python package {user}`ilan-gold` ({pr}`1726`)
|
|
37
|
+
- {guilabel}`rc1` Adopt the Scientific Python [deprecation schedule](https://scientific-python.org/specs/spec-0000/) {user}`ilan-gold` ({pr}`1768`)
|
|
38
|
+
- {guilabel}`rc1` Allow {mod}`zarr` v3 writing of data {user}`ilan-gold` ({pr}`1892`)
|
|
39
|
+
- {guilabel}`rc1` {func}`anndata.register_anndata_namespace` functionality for adding custom functionality to an {class}`~anndata.AnnData` object {user}`srivarra` ({pr}`1870`)
|
|
40
|
+
- {guilabel}`rc2` Allow xarray Datasets to be used for obs/var/obsm/varm. {user}`ilia-kats` ({pr}`1966`)
|
|
41
|
+
- {guilabel}`rc4` {class}`anndata.experimental.backed.Dataset2D` now takes a compositional approach to wrapping {class}`xarray.Dataset` which may have breaking changes over the past release versions. {user}`ilan-gold` ({pr}`1997`)
|
|
42
|
+
- {guilabel}`rc4` Use {attr}`numpy.dtypes.StringDType` with `na_object` set to {attr}`pandas.NA` for nullable string data with {class}`anndata.experimental.backed.Dataset2D` {user}`ilan-gold` ({pr}`2011`)
|
|
43
|
+
|
|
44
|
+
#### Performance
|
|
45
|
+
|
|
46
|
+
- {guilabel}`rc2` Load AnnLoader lazily to prevent expensive unnecessary `torch` imports when its available on the system. {user}`Zethson` & {user}`flying-sheep` ({pr}`1950`)
|
|
47
|
+
- {guilabel}`rc4` Improve {func}`~anndata.experimental.read_elem_lazy` performance for `h5ad` files by not caching `indptr`. {user}`ilan-gold` ({pr}`2005`)
|
|
48
|
+
|
|
49
|
+
#### Development
|
|
50
|
+
|
|
51
|
+
- {guilabel}`rc4` Temporarily bound {mod}`zarr` to `<3.1` until {pr}`1995` is merged to handle the new data type structure. {user}`ilan-gold` ({pr}`2013`)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
(v0.12.1)=
|
|
2
|
+
### 0.12.1 {small}`2025-07-23`
|
|
3
|
+
|
|
4
|
+
### Bug fixes
|
|
5
|
+
|
|
6
|
+
- Fix `chunks` argument for {func}`anndata.experimental.read_elem_lazy` so that it uses the on-disk chunking when possible, and allow users to pass this argument through to the reading of {class}`anndata.experimental.backed.Dataset2D` {user}`ilan-gold` ({pr}`2033`)
|
|
7
|
+
|
|
8
|
+
### Performance
|
|
9
|
+
|
|
10
|
+
- Improve integer indexing performance of `h5` 1d arrays that are opened via {func}`anndata.experimental.read_elem_lazy` {user}`ilan-gold` ({pr}`2035`)
|
|
@@ -1,9 +1,26 @@
|
|
|
1
1
|
# zarr-v3 Guide/Roadmap
|
|
2
2
|
|
|
3
|
-
`anndata` now uses the much improved {mod}`zarr` v3 package and also allows writing of datasets in the v3 format via {attr}`anndata.settings.zarr_write_format`, with the exception of structured arrays.
|
|
3
|
+
`anndata` now uses the much improved {mod}`zarr` v3 package and also allows writing of datasets in the v3 format via {attr}`anndata.settings.zarr_write_format` via {func}`anndata.io.write_zarr` or {meth}`anndata.AnnData.write_zarr`, with the exception of structured arrays.
|
|
4
4
|
Users should notice a significant performance improvement, especially for cloud data, but also likely for local data as well.
|
|
5
5
|
Here is a quick guide on some of our learnings so far:
|
|
6
6
|
|
|
7
|
+
## Consolidated Metadata
|
|
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:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
g = zarr.open_group(orig_path, mode="a", use_consolidated=False)
|
|
13
|
+
ad.io.write_elem(
|
|
14
|
+
g,
|
|
15
|
+
"obs",
|
|
16
|
+
obs,
|
|
17
|
+
dataset_kwargs=dict(chunks=(250,)),
|
|
18
|
+
)
|
|
19
|
+
zarr.consolidate_metadata(g.store)
|
|
20
|
+
```
|
|
21
|
+
|
|
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`.
|
|
23
|
+
|
|
7
24
|
## Remote data
|
|
8
25
|
|
|
9
26
|
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`.
|
|
@@ -31,7 +48,7 @@ import anndata as ad
|
|
|
31
48
|
from collections.abc import Mapping
|
|
32
49
|
from typing import Any
|
|
33
50
|
|
|
34
|
-
|
|
51
|
+
g = zarr.open_group(orig_path, mode="a", use_consolidated=False, zarr_version=3) # zarr_version 3 is default but note that sharding only works with v3!
|
|
35
52
|
|
|
36
53
|
def write_sharded(group: zarr.Group, adata: ad.AnnData):
|
|
37
54
|
def callback(
|
|
@@ -36,6 +36,7 @@ overrides.matrix.deps.python = [
|
|
|
36
36
|
overrides.matrix.deps.features = [
|
|
37
37
|
{ if = [ "stable", "pre" ], value = "test" },
|
|
38
38
|
]
|
|
39
|
+
overrides.matrix.deps.extra-args = { if = [ "stable", "pre" ], value = [ "--strict-warnings" ] }
|
|
39
40
|
|
|
40
41
|
[[envs.hatch-test.matrix]]
|
|
41
42
|
deps = [ "stable", "pre", "min" ]
|
|
@@ -36,18 +36,16 @@ classifiers = [
|
|
|
36
36
|
"Topic :: Scientific/Engineering :: Visualization",
|
|
37
37
|
]
|
|
38
38
|
dependencies = [
|
|
39
|
-
|
|
40
|
-
"
|
|
41
|
-
"numpy>=1.25",
|
|
39
|
+
"pandas >=2.1.0, !=2.1.2",
|
|
40
|
+
"numpy>=1.26",
|
|
42
41
|
# https://github.com/scverse/anndata/issues/1434
|
|
43
|
-
"scipy >=1.
|
|
42
|
+
"scipy >=1.12",
|
|
44
43
|
"h5py>=3.8",
|
|
45
44
|
"natsort",
|
|
46
45
|
"packaging>=24.2",
|
|
47
46
|
"array_api_compat>=1.7.1",
|
|
48
47
|
"legacy-api-wrap",
|
|
49
|
-
|
|
50
|
-
"zarr >=2.18.7, !=3.0.0, !=3.0.1, !=3.0.2, !=3.0.3, !=3.0.4, !=3.0.5, !=3.0.6, !=3.0.7, <3.1",
|
|
48
|
+
"zarr >=2.18.7, !=3.0.*",
|
|
51
49
|
]
|
|
52
50
|
dynamic = [ "version" ]
|
|
53
51
|
|
|
@@ -96,16 +94,14 @@ test-min = [
|
|
|
96
94
|
"joblib",
|
|
97
95
|
"boltons",
|
|
98
96
|
"scanpy>=1.10",
|
|
99
|
-
|
|
97
|
+
# TODO: Is 1.0dev1 a real pre-release? https://pypi.org/project/httpx/#history
|
|
98
|
+
"httpx<1.0", # For data downloading
|
|
100
99
|
"dask[distributed]",
|
|
101
100
|
"awkward>=2.3.2",
|
|
102
|
-
"pyarrow",
|
|
101
|
+
"pyarrow<21", # https://github.com/scikit-hep/awkward/issues/3579
|
|
103
102
|
"anndata[dask]",
|
|
104
103
|
]
|
|
105
|
-
test = [
|
|
106
|
-
"anndata[test-min,lazy]",
|
|
107
|
-
"pandas>=2.1.0",
|
|
108
|
-
] # pandas 2.1.0 needs to be specified for xarray to work with min-deps script
|
|
104
|
+
test = [ "anndata[test-min,lazy]" ]
|
|
109
105
|
gpu = [ "cupy" ]
|
|
110
106
|
cu12 = [ "cupy-cuda12x" ]
|
|
111
107
|
cu11 = [ "cupy-cuda11x" ]
|
|
@@ -150,6 +146,7 @@ addopts = [
|
|
|
150
146
|
filterwarnings = [
|
|
151
147
|
"ignore::anndata._warnings.OldFormatWarning",
|
|
152
148
|
"ignore::anndata._warnings.ExperimentalFeatureWarning",
|
|
149
|
+
"ignore:.*first_column_names:FutureWarning:scanpy", # scanpy 1.10.x
|
|
153
150
|
]
|
|
154
151
|
# When `--strict-warnings` is used, all warnings are treated as errors, except those:
|
|
155
152
|
filterwarnings_when_strict = [
|
|
@@ -162,6 +159,8 @@ filterwarnings_when_strict = [
|
|
|
162
159
|
"default:The codec `vlen-utf8:UserWarning",
|
|
163
160
|
"default:The dtype `StringDType():UserWarning",
|
|
164
161
|
"default:Consolidated metadata is:UserWarning",
|
|
162
|
+
"default:.*Structured:zarr.core.dtype.common.UnstableSpecificationWarning",
|
|
163
|
+
"default:.*FixedLengthUTF32:zarr.core.dtype.common.UnstableSpecificationWarning",
|
|
165
164
|
]
|
|
166
165
|
python_files = "test_*.py"
|
|
167
166
|
testpaths = [
|
|
@@ -172,7 +171,7 @@ testpaths = [
|
|
|
172
171
|
]
|
|
173
172
|
# For some reason this effects how logging is shown when tests are run
|
|
174
173
|
xfail_strict = true
|
|
175
|
-
markers = [ "gpu: mark test to run on GPU" ]
|
|
174
|
+
markers = [ "gpu: mark test to run on GPU", "zarr_io: mark tests that involve zarr io" ]
|
|
176
175
|
|
|
177
176
|
[tool.ruff]
|
|
178
177
|
src = [ "src" ]
|
|
@@ -212,6 +211,7 @@ ignore = [
|
|
|
212
211
|
"E731", # Do not assign a lambda expression, use a def -> AnnData allows lambda expression assignments,
|
|
213
212
|
"E741", # allow I, O, l as variable names -> I is the identity matrix, i, j, k, l is reasonable indexing notation
|
|
214
213
|
"TID252", # We use relative imports from parent modules
|
|
214
|
+
"PLC0415", # We use a lot of non-top-level imports
|
|
215
215
|
"PLR2004", # “2” is often not too “magic” a number
|
|
216
216
|
"PLW2901", # Shadowing loop variables isn’t a big deal
|
|
217
217
|
]
|
|
@@ -56,13 +56,13 @@ if TYPE_CHECKING:
|
|
|
56
56
|
|
|
57
57
|
from zarr.storage import StoreLike
|
|
58
58
|
|
|
59
|
-
from ..compat import Index1D, XDataset
|
|
59
|
+
from ..compat import Index1D, Index1DNorm, XDataset
|
|
60
60
|
from ..typing import XDataType
|
|
61
61
|
from .aligned_mapping import AxisArraysView, LayersView, PairwiseArraysView
|
|
62
62
|
from .index import Index
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
65
|
+
class AnnData(metaclass=utils.DeprecationMixinMeta): # noqa: PLW1641
|
|
66
66
|
"""\
|
|
67
67
|
An annotated data matrix.
|
|
68
68
|
|
|
@@ -197,6 +197,11 @@ class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
|
197
197
|
|
|
198
198
|
_accessors: ClassVar[set[str]] = set()
|
|
199
199
|
|
|
200
|
+
# view attributes
|
|
201
|
+
_adata_ref: AnnData | None
|
|
202
|
+
_oidx: Index1DNorm | None
|
|
203
|
+
_vidx: Index1DNorm | None
|
|
204
|
+
|
|
200
205
|
@old_positionals(
|
|
201
206
|
"obsm",
|
|
202
207
|
"varm",
|
|
@@ -226,8 +231,8 @@ class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
|
226
231
|
asview: bool = False,
|
|
227
232
|
obsp: np.ndarray | Mapping[str, Sequence[Any]] | None = None,
|
|
228
233
|
varp: np.ndarray | Mapping[str, Sequence[Any]] | None = None,
|
|
229
|
-
oidx:
|
|
230
|
-
vidx:
|
|
234
|
+
oidx: Index1DNorm | int | np.integer | None = None,
|
|
235
|
+
vidx: Index1DNorm | int | np.integer | None = None,
|
|
231
236
|
):
|
|
232
237
|
# check for any multi-indices that aren’t later checked in coerce_array
|
|
233
238
|
for attr, key in [(obs, "obs"), (var, "var"), (X, "X")]:
|
|
@@ -237,6 +242,8 @@ class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
|
237
242
|
if not isinstance(X, AnnData):
|
|
238
243
|
msg = "`X` has to be an AnnData object."
|
|
239
244
|
raise ValueError(msg)
|
|
245
|
+
assert oidx is not None
|
|
246
|
+
assert vidx is not None
|
|
240
247
|
self._init_as_view(X, oidx, vidx)
|
|
241
248
|
else:
|
|
242
249
|
self._init_as_actual(
|
|
@@ -256,7 +263,12 @@ class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
|
256
263
|
filemode=filemode,
|
|
257
264
|
)
|
|
258
265
|
|
|
259
|
-
def _init_as_view(
|
|
266
|
+
def _init_as_view(
|
|
267
|
+
self,
|
|
268
|
+
adata_ref: AnnData,
|
|
269
|
+
oidx: Index1DNorm | int | np.integer,
|
|
270
|
+
vidx: Index1DNorm | int | np.integer,
|
|
271
|
+
):
|
|
260
272
|
if adata_ref.isbacked and adata_ref.is_view:
|
|
261
273
|
msg = (
|
|
262
274
|
"Currently, you cannot index repeatedly into a backed AnnData, "
|
|
@@ -277,6 +289,9 @@ class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
|
277
289
|
vidx += adata_ref.n_vars * (vidx < 0)
|
|
278
290
|
vidx = slice(vidx, vidx + 1, 1)
|
|
279
291
|
if adata_ref.is_view:
|
|
292
|
+
assert adata_ref._adata_ref is not None
|
|
293
|
+
assert adata_ref._oidx is not None
|
|
294
|
+
assert adata_ref._vidx is not None
|
|
280
295
|
prev_oidx, prev_vidx = adata_ref._oidx, adata_ref._vidx
|
|
281
296
|
adata_ref = adata_ref._adata_ref
|
|
282
297
|
oidx, vidx = _resolve_idxs((prev_oidx, prev_vidx), (oidx, vidx), adata_ref)
|
|
@@ -1004,7 +1019,9 @@ class AnnData(metaclass=utils.DeprecationMixinMeta):
|
|
|
1004
1019
|
|
|
1005
1020
|
write_attribute(self.file._file, attr, value)
|
|
1006
1021
|
|
|
1007
|
-
def _normalize_indices(
|
|
1022
|
+
def _normalize_indices(
|
|
1023
|
+
self, index: Index | None
|
|
1024
|
+
) -> tuple[Index1DNorm | int | np.integer, Index1DNorm | int | np.integer]:
|
|
1008
1025
|
return _normalize_indices(index, self.obs_names, self.var_names)
|
|
1009
1026
|
|
|
1010
1027
|
# TODO: this is not quite complete...
|
|
@@ -14,18 +14,18 @@ from ..compat import AwkArray, CSArray, CSMatrix, DaskArray, XDataArray
|
|
|
14
14
|
from .xarray import Dataset2D
|
|
15
15
|
|
|
16
16
|
if TYPE_CHECKING:
|
|
17
|
-
from ..compat import Index, Index1D
|
|
17
|
+
from ..compat import Index, Index1D, Index1DNorm
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
def _normalize_indices(
|
|
21
21
|
index: Index | None, names0: pd.Index, names1: pd.Index
|
|
22
|
-
) -> tuple[
|
|
22
|
+
) -> tuple[Index1DNorm | int | np.integer, Index1DNorm | int | np.integer]:
|
|
23
23
|
# deal with tuples of length 1
|
|
24
24
|
if isinstance(index, tuple) and len(index) == 1:
|
|
25
25
|
index = index[0]
|
|
26
26
|
# deal with pd.Series
|
|
27
27
|
if isinstance(index, pd.Series):
|
|
28
|
-
index
|
|
28
|
+
index = index.values
|
|
29
29
|
if isinstance(index, tuple):
|
|
30
30
|
# TODO: The series should probably be aligned first
|
|
31
31
|
index = tuple(i.values if isinstance(i, pd.Series) else i for i in index)
|
|
@@ -36,15 +36,8 @@ def _normalize_indices(
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def _normalize_index( # noqa: PLR0911, PLR0912
|
|
39
|
-
indexer:
|
|
40
|
-
|
|
41
|
-
| int
|
|
42
|
-
| str
|
|
43
|
-
| Sequence[bool | int | np.integer]
|
|
44
|
-
| np.ndarray
|
|
45
|
-
| pd.Index,
|
|
46
|
-
index: pd.Index,
|
|
47
|
-
) -> slice | int | np.ndarray: # ndarray of int or bool
|
|
39
|
+
indexer: Index1D, index: pd.Index
|
|
40
|
+
) -> Index1DNorm | int | np.integer:
|
|
48
41
|
# TODO: why is this here? All tests pass without it and it seems at the minimum not strict enough.
|
|
49
42
|
if not isinstance(index, pd.RangeIndex) and index.dtype in (np.float64, np.int64):
|
|
50
43
|
msg = f"Don’t call _normalize_index with non-categorical/string names and non-range index {index}"
|
|
@@ -212,7 +205,7 @@ def _subset_awkarray(a: AwkArray, subset_idx: Index):
|
|
|
212
205
|
|
|
213
206
|
# Registration for SparseDataset occurs in sparse_dataset.py
|
|
214
207
|
@_subset.register(h5py.Dataset)
|
|
215
|
-
def _subset_dataset(d, subset_idx):
|
|
208
|
+
def _subset_dataset(d: h5py.Dataset, subset_idx: Index):
|
|
216
209
|
if not isinstance(subset_idx, tuple):
|
|
217
210
|
subset_idx = (subset_idx,)
|
|
218
211
|
ordered = list(subset_idx)
|
|
@@ -904,12 +904,6 @@ def concat_arrays( # noqa: PLR0911, PLR0912
|
|
|
904
904
|
],
|
|
905
905
|
format="csr",
|
|
906
906
|
)
|
|
907
|
-
scipy_version = Version(scipy.__version__)
|
|
908
|
-
# Bug where xstack produces a matrix not an array in 1.11.*
|
|
909
|
-
if use_sparse_array and (scipy_version.major, scipy_version.minor) == (1, 11):
|
|
910
|
-
if mat.format == "csc":
|
|
911
|
-
return sparse.csc_array(mat)
|
|
912
|
-
return sparse.csr_array(mat)
|
|
913
907
|
return mat
|
|
914
908
|
else:
|
|
915
909
|
return np.concatenate(
|
|
@@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|
|
17
17
|
from collections.abc import Mapping, Sequence
|
|
18
18
|
from typing import ClassVar
|
|
19
19
|
|
|
20
|
-
from ..compat import CSMatrix
|
|
20
|
+
from ..compat import CSMatrix, Index, Index1DNorm
|
|
21
21
|
from .aligned_mapping import AxisArraysView
|
|
22
22
|
from .anndata import AnnData
|
|
23
23
|
from .sparse_dataset import BaseCompressedSparseDataset
|
|
@@ -121,7 +121,7 @@ class Raw:
|
|
|
121
121
|
def obs_names(self) -> pd.Index[str]:
|
|
122
122
|
return self._adata.obs_names
|
|
123
123
|
|
|
124
|
-
def __getitem__(self, index):
|
|
124
|
+
def __getitem__(self, index: Index) -> Raw:
|
|
125
125
|
oidx, vidx = self._normalize_indices(index)
|
|
126
126
|
|
|
127
127
|
# To preserve two dimensional shape
|
|
@@ -169,7 +169,9 @@ class Raw:
|
|
|
169
169
|
uns=self._adata.uns.copy(),
|
|
170
170
|
)
|
|
171
171
|
|
|
172
|
-
def _normalize_indices(
|
|
172
|
+
def _normalize_indices(
|
|
173
|
+
self, packed_index: Index
|
|
174
|
+
) -> tuple[Index1DNorm | int | np.integer, Index1DNorm | int | np.integer]:
|
|
173
175
|
# deal with slicing with pd.Series
|
|
174
176
|
if isinstance(packed_index, pd.Series):
|
|
175
177
|
packed_index = packed_index.values
|