anndata 0.12.0rc4__tar.gz → 0.12.1__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.1}/.github/workflows/test-cpu.yml +2 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/.pre-commit-config.yaml +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.1}/PKG-INFO +9 -10
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/asv.conf.json +2 -0
- anndata-0.12.1/benchmarks/benchmarks/dataset2d.py +61 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/benchmarks/sparse_dataset.py +18 -7
- {anndata-0.12.0rc4 → anndata-0.12.1}/biome.jsonc +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/conf.py +4 -3
- anndata-0.12.1/docs/release-notes/0.12.0.md +51 -0
- anndata-0.12.1/docs/release-notes/0.12.1.md +10 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/tutorials/zarr-v3.md +17 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/pyproject.toml +10 -13
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/aligned_df.py +1 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/anndata.py +1 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/merge.py +0 -6
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/sparse_dataset.py +5 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/xarray.py +7 -4
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/h5ad.py +1 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/read.py +5 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/specs/lazy_methods.py +25 -15
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/specs/methods.py +18 -16
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/specs/registry.py +15 -4
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/zarr.py +0 -14
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_settings.py +5 -2
- anndata-0.12.1/src/anndata/_settings.pyi +49 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/backed/_lazy_arrays.py +27 -5
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/tests/helpers.py +8 -24
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/utils.py +3 -4
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/testing/anndata/_pytest.py +4 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/conftest.py +13 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/lazy/conftest.py +12 -3
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/lazy/test_read.py +33 -3
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_awkward.py +2 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_backed_hdf5.py +8 -5
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_backed_sparse.py +10 -10
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_base.py +3 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_concatenate_disk.py +12 -5
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_deprecations.py +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_backwards_compat.py +3 -3
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_dispatched.py +10 -5
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_elementwise.py +85 -15
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_warnings.py +2 -2
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_readwrite.py +20 -1
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_settings.py +19 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_structured_arrays.py +12 -21
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_utils.py +4 -2
- 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.1}/.cirun.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.codecov.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.editorconfig +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/enhancement-request.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/ISSUE_TEMPLATE/question.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/benchmark.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/check-pr-milestoned.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/close-stale.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/codespell.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/label-stale.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/publish.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.github/workflows/test-gpu.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.gitignore +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.gitmodules +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.prettierignore +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.prettierrc.yaml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.readthedocs.yml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.taplo.toml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.vscode/launch.json +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/.vscode/settings.json +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/LICENSE +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/README.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/README.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/benchmarks/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/benchmarks/anndata.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/benchmarks/readwrite.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/benchmarks/benchmarks/utils.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/ci/constraints.txt +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/ci/scripts/min-deps.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/ci/scripts/towncrier_automation.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/Makefile +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/_key_contributors.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/_static/img/anndata_schema.svg +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/_templates/autosummary/class.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/api.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/benchmark-read-write.ipynb +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/benchmarks.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/concatenation.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/contributing.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/extensions/autosummary_skip_inherited.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/extensions/no_skip_abc_members.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/extensions/patch_myst_cite.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/fileformat-prose.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/index.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/interoperability.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/news.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/references.rst +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.1.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.3.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.4.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.5.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.6.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.7.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.8.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.10.9.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.11.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.11.1.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.11.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.11.3.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.11.4.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.4.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.5.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.6.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.6.x.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.3.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.4.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.5.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.6.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.7.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.7.8.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.8.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.9.0.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.9.1.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/0.9.2.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/release-notes/index.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/docs/tutorials/index.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/hatch.toml +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/access.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/aligned_mapping.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/extensions.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/file_backing.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/index.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/raw.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/storage.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_core/views.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/specs/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/utils.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_io/write.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_types.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_version.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/_warnings.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/abc.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/compat/__init__.py +7 -7
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/_dispatch_io.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/backed/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/backed/_compat.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/backed/_io.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/merge.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/multi_files/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/multi_files/_anncollection.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/pytorch/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/experimental/pytorch/_annloader.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/io.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/logging.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/tests/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/types.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/anndata/typing.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/testing/anndata/__init__.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/testing/anndata/_doctest.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/src/testing/anndata/py.typed +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/adata-comments.tsv +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/adata.csv +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/archives/readme.md +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/archives/v0.7.0/adata.h5ad +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/archives/v0.7.0/adata.zarr.zip +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/archives/v0.7.8/adata.h5ad +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/archives/v0.7.8/adata.zarr.zip +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/excel.xlsx +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/data/umi_tools.tsv.gz +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/lazy/test_concat.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/lazy/test_write.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_anncollection.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_annot.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_backed_dense.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_concatenate.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_dask.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_dask_view_mem.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_extensions.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_get_vector.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_gpu.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_helpers.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_inplace_subset.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_conversion.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_partial.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_io_utils.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_layers.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_obsmvarm.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_obspvarp.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_raw.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_repr.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_transpose.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_uns.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_views.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_x.py +0 -0
- {anndata-0.12.0rc4 → anndata-0.12.1}/tests/test_xarray.py +0 -0
|
@@ -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:
|
|
@@ -70,7 +71,7 @@ jobs:
|
|
|
70
71
|
run: uvx hatch -v env create ${{ matrix.env.name }}
|
|
71
72
|
|
|
72
73
|
- 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
|
|
74
|
+
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}}"
|
|
74
75
|
|
|
75
76
|
- name: Upload coverage data
|
|
76
77
|
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.1
|
|
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`)
|
|
@@ -4,6 +4,23 @@
|
|
|
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`.
|
|
@@ -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" ]
|
|
@@ -172,7 +168,7 @@ testpaths = [
|
|
|
172
168
|
]
|
|
173
169
|
# For some reason this effects how logging is shown when tests are run
|
|
174
170
|
xfail_strict = true
|
|
175
|
-
markers = [ "gpu: mark test to run on GPU" ]
|
|
171
|
+
markers = [ "gpu: mark test to run on GPU", "zarr_io: mark tests that involve zarr io" ]
|
|
176
172
|
|
|
177
173
|
[tool.ruff]
|
|
178
174
|
src = [ "src" ]
|
|
@@ -212,6 +208,7 @@ ignore = [
|
|
|
212
208
|
"E731", # Do not assign a lambda expression, use a def -> AnnData allows lambda expression assignments,
|
|
213
209
|
"E741", # allow I, O, l as variable names -> I is the identity matrix, i, j, k, l is reasonable indexing notation
|
|
214
210
|
"TID252", # We use relative imports from parent modules
|
|
211
|
+
"PLC0415", # We use a lot of non-top-level imports
|
|
215
212
|
"PLR2004", # “2” is often not too “magic” a number
|
|
216
213
|
"PLW2901", # Shadowing loop variables isn’t a big deal
|
|
217
214
|
]
|
|
@@ -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(
|
|
@@ -165,7 +165,11 @@ class BackedSparseMatrix(_cs_matrix):
|
|
|
165
165
|
def _get_contiguous_compressed_slice(
|
|
166
166
|
self, s: slice
|
|
167
167
|
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
168
|
-
new_indptr = self.indptr[s.start : s.stop + 1]
|
|
168
|
+
new_indptr = self.indptr[s.start : s.stop + 1]
|
|
169
|
+
# If indptr is cached, we need to make a copy of the subset
|
|
170
|
+
# so as not to alter the underlying cached data.
|
|
171
|
+
if isinstance(self.indptr, np.ndarray):
|
|
172
|
+
new_indptr = new_indptr.copy()
|
|
169
173
|
|
|
170
174
|
start = new_indptr[0]
|
|
171
175
|
stop = new_indptr[-1]
|
|
@@ -245,7 +245,7 @@ class Dataset2D:
|
|
|
245
245
|
if df.index.name != index_key and index_key is not None:
|
|
246
246
|
df = df.set_index(index_key)
|
|
247
247
|
for col in set(self.columns) - non_nullable_string_cols:
|
|
248
|
-
df[col] =
|
|
248
|
+
df[col] = df[col].astype(dtype="string")
|
|
249
249
|
df.index.name = None # matches old AnnData object
|
|
250
250
|
return df
|
|
251
251
|
|
|
@@ -389,9 +389,12 @@ class Dataset2D:
|
|
|
389
389
|
}
|
|
390
390
|
el = self.ds.drop_vars(extension_arrays.keys())
|
|
391
391
|
el = el.reindex({index_dim: index}, method=None, fill_value=fill_value)
|
|
392
|
-
for col in
|
|
393
|
-
el[col] =
|
|
394
|
-
|
|
392
|
+
for col, data in extension_arrays.items():
|
|
393
|
+
el[col] = XDataArray.from_series(
|
|
394
|
+
pd.Series(data.data, index=self.index).reindex(
|
|
395
|
+
index.rename(self.index.name) if index is not None else index,
|
|
396
|
+
fill_value=fill_value,
|
|
397
|
+
)
|
|
395
398
|
)
|
|
396
399
|
return Dataset2D(el)
|
|
397
400
|
|
|
@@ -176,7 +176,7 @@ def read_h5ad_backed(
|
|
|
176
176
|
|
|
177
177
|
def read_h5ad(
|
|
178
178
|
filename: PathLike[str] | str,
|
|
179
|
-
backed: Literal["r", "r+"] | bool | None = None,
|
|
179
|
+
backed: Literal["r", "r+"] | bool | None = None, # noqa: FBT001
|
|
180
180
|
*,
|
|
181
181
|
as_sparse: Sequence[str] = (),
|
|
182
182
|
as_sparse_fmt: type[CSMatrix] = sparse.csr_matrix,
|
|
@@ -22,9 +22,11 @@ if TYPE_CHECKING:
|
|
|
22
22
|
from collections.abc import Generator, Iterable, Iterator, Mapping
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
@old_positionals("first_column_names", "dtype")
|
|
25
26
|
def read_csv(
|
|
26
27
|
filename: PathLike[str] | str | Iterator[str],
|
|
27
28
|
delimiter: str | None = ",",
|
|
29
|
+
*,
|
|
28
30
|
first_column_names: bool | None = None,
|
|
29
31
|
dtype: str = "float32",
|
|
30
32
|
) -> AnnData:
|
|
@@ -331,9 +333,11 @@ def read_mtx(filename: PathLike[str] | str, dtype: str = "float32") -> AnnData:
|
|
|
331
333
|
return AnnData(X)
|
|
332
334
|
|
|
333
335
|
|
|
336
|
+
@old_positionals("first_column_names", "dtype")
|
|
334
337
|
def read_text(
|
|
335
338
|
filename: PathLike[str] | str | Iterator[str],
|
|
336
339
|
delimiter: str | None = None,
|
|
340
|
+
*,
|
|
337
341
|
first_column_names: bool | None = None,
|
|
338
342
|
dtype: str = "float32",
|
|
339
343
|
) -> AnnData:
|
|
@@ -381,7 +385,7 @@ def _iter_lines(file_like: Iterable[str]) -> Generator[str, None, None]:
|
|
|
381
385
|
def _read_text( # noqa: PLR0912, PLR0915
|
|
382
386
|
f: Iterator[str],
|
|
383
387
|
delimiter: str | None,
|
|
384
|
-
first_column_names: bool | None,
|
|
388
|
+
first_column_names: bool | None, # noqa: FBT001
|
|
385
389
|
dtype: str,
|
|
386
390
|
) -> AnnData:
|
|
387
391
|
comments = []
|
|
@@ -132,7 +132,7 @@ def read_sparse_as_dask(
|
|
|
132
132
|
path_or_sparse_dataset = (
|
|
133
133
|
Path(filename(elem))
|
|
134
134
|
if isinstance(elem, H5Group)
|
|
135
|
-
else ad.io.sparse_dataset(elem)
|
|
135
|
+
else ad.io.sparse_dataset(elem, should_cache_indptr=False)
|
|
136
136
|
)
|
|
137
137
|
elem_name = get_elem_name(elem)
|
|
138
138
|
shape: tuple[int, int] = tuple(elem.attrs["shape"])
|
|
@@ -177,21 +177,37 @@ def read_sparse_as_dask(
|
|
|
177
177
|
return da_mtx
|
|
178
178
|
|
|
179
179
|
|
|
180
|
+
def resolve_chunks(
|
|
181
|
+
elem: H5Array | ZarrArray,
|
|
182
|
+
chunks_arg: tuple[int, ...] | None,
|
|
183
|
+
shape: tuple[int, ...],
|
|
184
|
+
) -> tuple[int, ...]:
|
|
185
|
+
shape = tuple(elem.shape)
|
|
186
|
+
if chunks_arg is not None:
|
|
187
|
+
# None and -1 on a given axis indicate that one should use the shape
|
|
188
|
+
# in `dask`'s semantics.
|
|
189
|
+
return tuple(
|
|
190
|
+
c if c not in {None, -1} else s
|
|
191
|
+
for c, s in zip(chunks_arg, shape, strict=True)
|
|
192
|
+
)
|
|
193
|
+
elif elem.chunks is None: # h5 unchunked
|
|
194
|
+
return tuple(min(_DEFAULT_STRIDE, s) for s in shape)
|
|
195
|
+
return elem.chunks
|
|
196
|
+
|
|
197
|
+
|
|
180
198
|
@_LAZY_REGISTRY.register_read(H5Array, IOSpec("string-array", "0.2.0"))
|
|
181
199
|
def read_h5_string_array(
|
|
182
200
|
elem: H5Array,
|
|
183
201
|
*,
|
|
184
202
|
_reader: LazyReader,
|
|
185
|
-
chunks: tuple[int
|
|
203
|
+
chunks: tuple[int] | None = None,
|
|
186
204
|
) -> DaskArray:
|
|
187
205
|
import dask.array as da
|
|
188
206
|
|
|
189
207
|
from anndata._io.h5ad import read_dataset
|
|
190
208
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
chunks=chunks if chunks is not None else (_DEFAULT_STRIDE,) * len(elem.shape),
|
|
194
|
-
)
|
|
209
|
+
chunks = resolve_chunks(elem, chunks, tuple(elem.shape))
|
|
210
|
+
return da.from_array(read_dataset(elem), chunks=chunks)
|
|
195
211
|
|
|
196
212
|
|
|
197
213
|
@_LAZY_REGISTRY.register_read(H5Array, IOSpec("array", "0.2.0"))
|
|
@@ -204,13 +220,7 @@ def read_h5_array(
|
|
|
204
220
|
elem_name: str = elem.name
|
|
205
221
|
shape = tuple(elem.shape)
|
|
206
222
|
dtype = elem.dtype
|
|
207
|
-
chunks = (
|
|
208
|
-
tuple(
|
|
209
|
-
c if c not in {None, -1} else s for c, s in zip(chunks, shape, strict=True)
|
|
210
|
-
)
|
|
211
|
-
if chunks is not None
|
|
212
|
-
else tuple(min(_DEFAULT_STRIDE, s) for s in shape)
|
|
213
|
-
)
|
|
223
|
+
chunks = resolve_chunks(elem, chunks, shape)
|
|
214
224
|
|
|
215
225
|
chunk_layout = tuple(
|
|
216
226
|
compute_chunk_layout_for_axis_size(chunks[i], shape[i])
|
|
@@ -228,7 +238,6 @@ def read_h5_array(
|
|
|
228
238
|
def read_zarr_array(
|
|
229
239
|
elem: ZarrArray, *, _reader: LazyReader, chunks: tuple[int, ...] | None = None
|
|
230
240
|
) -> DaskArray:
|
|
231
|
-
chunks: tuple[int, ...] = chunks if chunks is not None else elem.chunks
|
|
232
241
|
import dask.array as da
|
|
233
242
|
|
|
234
243
|
return da.from_zarr(elem, chunks=chunks)
|
|
@@ -284,9 +293,10 @@ def read_dataframe(
|
|
|
284
293
|
*,
|
|
285
294
|
_reader: LazyReader,
|
|
286
295
|
use_range_index: bool = False,
|
|
296
|
+
chunks: tuple[int] | None = None,
|
|
287
297
|
) -> Dataset2D:
|
|
288
298
|
elem_dict = {
|
|
289
|
-
k: _reader.read_elem(elem[k])
|
|
299
|
+
k: _reader.read_elem(elem[k], chunks=chunks)
|
|
290
300
|
for k in [*elem.attrs["column-order"], elem.attrs["_index"]]
|
|
291
301
|
}
|
|
292
302
|
# If we use a range index, the coord axis needs to have the special dim name
|