blosc2 3.3.1__tar.gz → 3.3.3__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.
- {blosc2-3.3.1 → blosc2-3.3.3}/.pre-commit-config.yaml +1 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/ANNOUNCE.rst +5 -11
- {blosc2-3.3.1 → blosc2-3.3.3}/CMakeLists.txt +1 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/PKG-INFO +3 -2
- {blosc2-3.3.1 → blosc2-3.3.3}/RELEASE_NOTES.md +43 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/python-blosc2.rst +1 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/pyproject.toml +4 -3
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/__init__.py +1 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/blosc2_ext.pyx +2 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/core.py +42 -29
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/lazyexpr.py +117 -10
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/ndarray.py +48 -27
- blosc2-3.3.3/src/blosc2/version.py +1 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_evaluate.py +1 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_jit.py +1 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_lazyexpr.py +73 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_ndarray.py +8 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_reductions.py +10 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_transpose.py +27 -32
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_zeros.py +37 -0
- blosc2-3.3.1/src/blosc2/version.py +0 -1
- {blosc2-3.3.1 → blosc2-3.3.3}/.gitignore +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/.guix/modules/python-blosc2-package.scm +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/.guix-channel +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/CONTRIBUTING.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/LICENSE.txt +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/README.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/README_DEVELOPERS.md +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/RELEASING.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/code_of_conduct.md +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/_static/blosc-favicon_32x32.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/_static/blosc-favicon_64x64.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/_static/blosc-logo_128.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/_static/blosc-logo_256.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/_static/css/custom.css +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/conf.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/development/code-of-conduct.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/development/contributing.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/development/index.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/index.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/installation.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/overview.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/01.ndarray-basics.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/02.lazyarray-expressions.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/03.lazyarray-udf.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/04.reductions.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/05.persistent-reductions.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/06.remote_proxy.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/07.schunk-basics.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/08.schunk-slicing_and_beyond.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/10.ucodecs-ufilters.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/11.prefilters.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/12.postfilters.ipynb +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/blosc2-pipeline.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/blosc2-pipeline.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/lazyexpr-broadcast.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/reductions/3D-cube-plane.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/reductions/3D-cube.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/reductions/memory-access-2D-x.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/reductions/memory-access-2D-y.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/remote_proxy.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/backward.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/backward.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/decoder.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/decoder.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/decoder2.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/decoder2.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/encoder.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/encoder.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/encoder2.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/encoder2.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/forward.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials/images/ucodecs-filters/forward.svg +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/getting_started/tutorials.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/index.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/array_operations.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__getitem__.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__init__.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__len__.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__setitem__.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.append_data.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.decompress_chunk.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.delete_chunk.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.fill_special.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.filler.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.get_chunk.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.get_slice.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.insert_chunk.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.insert_data.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.iterchunks.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.iterchunks_info.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.postfilter.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.prefilter.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.remove_postfilter.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.remove_prefilter.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.to_cframe.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.update_chunk.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.update_data.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/c2array.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/classes.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/decorators.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/index.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/lazy_functions.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/lazyarray.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/linear_algebra.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/low_level.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/ndarray.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/ndfield.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/proxy.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/proxyndsource.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/proxysource.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/reduction_functions.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/save_load.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/schunk.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/storage.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/reference/utilities.rst +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/doc/release_notes/index.md +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/btune.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/c2array-get-slice.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/compress2_decompress2.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/compress_decompress.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/filler.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/gil.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/mmap-rw.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/arange-constructor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/asarray_.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/broadcast_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/buffer.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/bytedelta_filter.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/c2array_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/compute_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/compute_fields.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/compute_udf_numba.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/compute_where.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/copy_.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/empty_.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/eye-constructor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/filter_sort_fields.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/formats.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/fromiter-constructor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/general_expressions.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/getitem.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/iterchunks_info.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/jit-expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/jit-numpy-funcs.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/jit-reduc.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/linspace-constructor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/lists-vs-bools-idx.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/meta.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/ndarray_copy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/ndmean.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/persistency.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/proxy-carray.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/proxy-ndarray.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/reduce_and_enlarge.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/reduce_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/reduce_expr_save.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/reduce_string_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/resize_.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/work_with_numpy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ndarray/zfp_codec.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/pack_array.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/pack_tensor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/postfilter1.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/postfilter2.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/postfilter3.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/prefilter.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/save_tensor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/schunk.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/schunk_roundtrip.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ucodecs.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/ufilters.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/examples/vlmeta.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/generate_version.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/guix.scm +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/Complete-Write-Read-B2ND.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/M1-i386-vs-arm64-pack.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/M1-i386-vs-arm64-unpack.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/Read-Partial-Slices-B2ND.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/b2nd-2level-parts.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/eval-expr-full-mem-M2.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/eval-expr-scarce-mem-M2.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/lazyarray-dask-large.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/lazyarray-dask-small.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/lazyarray-expr-large.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/lazyarray-expr.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/linspace-compress.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/linspace-decompress.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/pack-array-cratios.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/reduc-float64-amd.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/images/reduc-float64-log-amd.png +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/pytest.ini +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/c2array.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/helpers.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/info.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/proxy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/schunk.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/src/blosc2/storage.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/conftest.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_auto_parts.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_buffer.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_c2array_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_c2array_reductions.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_c2array_udf.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_copy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_empty.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_full.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_get_slice_nchunks.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_getitem.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_iterchunks_info.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_lazyexpr_fields.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_lazyudf.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_lossy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_matmul.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_metalayers.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_mode.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_nans.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_numpy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_persistency.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_proxy.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_proxy_c2array.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_proxy_expr.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_resize.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_setitem.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_slice.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_squeeze.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/ndarray/test_struct_dtype.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_bytes_array.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_comp_info.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_compress2.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_compression_parameters.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_compressors.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_decompress.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_iterchunks.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_mmap.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_open.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_open_c2array.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_pathlib.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_postfilters.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_prefilters.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_proxy_schunk.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_python_blosc.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_constructor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_delete.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_get_slice.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_get_slice_nchunks.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_insert.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_set_slice.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_schunk_update.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_storage.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_tensor.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_ucodecs.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_ufilters.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/tests/test_vlmeta.py +0 -0
- {blosc2-3.3.1 → blosc2-3.3.3}/update_version.py +0 -0
|
@@ -1,16 +1,10 @@
|
|
|
1
|
-
Announcing Python-Blosc2 3.3.
|
|
1
|
+
Announcing Python-Blosc2 3.3.3
|
|
2
2
|
==============================
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
(
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
See PR #384. Thanks to Ricardo Sales Piquer (@ricardosp4).
|
|
9
|
-
|
|
10
|
-
We have also reduced the memory footprint of constructors like ``arange()``,
|
|
11
|
-
``linspace()`` and ``fromiter()`` by a large factor. As an example, a 5 TB
|
|
12
|
-
array of 8-byte floats now uses less than 200 MB of memory instead of
|
|
13
|
-
170 GB previously.
|
|
4
|
+
This is a bugfix release, with some minor optimizations. We improved the
|
|
5
|
+
correct chaining of *string* lazy expressions (there is still room for
|
|
6
|
+
improvement). Also, a new version of C-Blosc2 (v2.7.2.dev) that fixes
|
|
7
|
+
mmap issues on Windows is used; thanks to @JanSellner for the fix.
|
|
14
8
|
|
|
15
9
|
You can think of Python-Blosc2 3.x as an extension of NumPy/numexpr that:
|
|
16
10
|
|
|
@@ -50,7 +50,7 @@ else()
|
|
|
50
50
|
include(FetchContent)
|
|
51
51
|
FetchContent_Declare(blosc2
|
|
52
52
|
GIT_REPOSITORY https://github.com/Blosc/c-blosc2
|
|
53
|
-
GIT_TAG
|
|
53
|
+
GIT_TAG 3f9c085c0c0f357b140fb5a50d1f8df06de3383a # v2.17.1 + mmap fix
|
|
54
54
|
)
|
|
55
55
|
FetchContent_MakeAvailable(blosc2)
|
|
56
56
|
include_directories("${blosc2_SOURCE_DIR}/include")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: blosc2
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.3
|
|
4
4
|
Summary: A fast & compressed ndarray library with a flexible compute engine.
|
|
5
5
|
Author-Email: Blosc Development Team <blosc@blosc.org>
|
|
6
6
|
Maintainer-Email: Blosc Development Team <blosc@blosc.org>
|
|
@@ -15,12 +15,13 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
|
15
15
|
Classifier: Operating System :: Microsoft :: Windows
|
|
16
16
|
Classifier: Operating System :: Unix
|
|
17
17
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
19
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
20
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
21
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
22
|
Project-URL: homepage, https://github.com/Blosc/python-blosc2
|
|
22
23
|
Project-URL: documentation, https://www.blosc.org/python-blosc2/python-blosc2.html
|
|
23
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.10
|
|
24
25
|
Requires-Dist: numpy>=1.26
|
|
25
26
|
Requires-Dist: ndindex
|
|
26
27
|
Requires-Dist: msgpack
|
|
@@ -1,5 +1,48 @@
|
|
|
1
1
|
# Release notes
|
|
2
2
|
|
|
3
|
+
## Changes from 3.3.2 to 3.3.3
|
|
4
|
+
|
|
5
|
+
* Expand possibilities for chaining string-based lazy expressions to include
|
|
6
|
+
main operand types (LazyExpr and NDArray). Still have to incorporate other
|
|
7
|
+
data types (which do not have shape attribute, e.g. int, float etc.).
|
|
8
|
+
See #406.
|
|
9
|
+
|
|
10
|
+
* Fix indexing for lazy expressions, and allow use of None in getitem.
|
|
11
|
+
See PR #402.
|
|
12
|
+
|
|
13
|
+
* Fix incorrect appending of dim to computed reductions. See PR #404.
|
|
14
|
+
|
|
15
|
+
* Fix `blosc2.linspace()` for incompatible num/shape. See PR #408.
|
|
16
|
+
|
|
17
|
+
* Add support for NumPy dtypes that are n-dimensional (e.g.
|
|
18
|
+
`np.dtype(("<i4,>f4", (10,))),`).
|
|
19
|
+
|
|
20
|
+
* New MAX_DIM constant for the maximum number of dimensions supported.
|
|
21
|
+
This is useful for checking if a given array is too large to be handled.
|
|
22
|
+
|
|
23
|
+
* More refinements on guessing cache sizes for Linux.
|
|
24
|
+
|
|
25
|
+
* Update to C-Blosc2 2.17.2.dev. Now, we are forcing the flush of modified
|
|
26
|
+
pages only in write mode for mmap files. This fixes mmap issues on Windows.
|
|
27
|
+
Thanks to @JanSellner for the implementation.
|
|
28
|
+
|
|
29
|
+
## Changes from 3.3.1 to 3.3.2
|
|
30
|
+
|
|
31
|
+
* Fixed a bug in the determination of chunk shape for the `NDArray` constructor.
|
|
32
|
+
This was causing problems when creating `NDArray` instances with a CPU that
|
|
33
|
+
was reporting a L3 cache size close (or exceeding) 2 GB. See PR #392.
|
|
34
|
+
|
|
35
|
+
* Fixed a bug preventing the correct chaining of *string* lazy expressions for
|
|
36
|
+
logical operators (`&`, `|`, `^`...). See PR #391.
|
|
37
|
+
|
|
38
|
+
* More performance optimization for `blosc2.permute_dims`. Thanks to
|
|
39
|
+
Ricardo Sales Piquer (@ricardosp4) for the implementation.
|
|
40
|
+
|
|
41
|
+
* Now, storage defaults (`blosc2.storage_dflts`) are honored, even if no
|
|
42
|
+
`storage=` param is used in constructors.
|
|
43
|
+
|
|
44
|
+
* We are distributing Python 3.10 wheels now.
|
|
45
|
+
|
|
3
46
|
## Changes from 3.3.0 to 3.3.1
|
|
4
47
|
|
|
5
48
|
* In our effort to better adapt to better adapt to the array API
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
<p style="text-align: center; color: black; background-color: rgba(230, 169, 9, 0.65);">
|
|
8
8
|
<a href="https://github.com/Blosc/python-blosc2/blob/main/RELEASE_NOTES.md"
|
|
9
|
-
style="font-size: 1.5em;">Version 3.3.
|
|
9
|
+
style="font-size: 1.5em;">Version 3.3.2 released on 2025-05-01!</a>
|
|
10
10
|
<span style="display: inline-block; width: 20px;"></span>
|
|
11
11
|
<span style="font-family: monospace;">pip install blosc2 -U</span>
|
|
12
12
|
</p>
|
|
@@ -24,11 +24,12 @@ classifiers = [
|
|
|
24
24
|
"Operating System :: Microsoft :: Windows",
|
|
25
25
|
"Operating System :: Unix",
|
|
26
26
|
"Programming Language :: Python :: 3",
|
|
27
|
+
"Programming Language :: Python :: 3.10",
|
|
27
28
|
"Programming Language :: Python :: 3.11",
|
|
28
29
|
"Programming Language :: Python :: 3.12",
|
|
29
30
|
"Programming Language :: Python :: 3.13",
|
|
30
31
|
]
|
|
31
|
-
requires-python = ">=3.
|
|
32
|
+
requires-python = ">=3.10"
|
|
32
33
|
# Follow guidelines from https://scientific-python.org/specs/spec-0000/
|
|
33
34
|
dependencies = [
|
|
34
35
|
"numpy>=1.26",
|
|
@@ -40,7 +41,7 @@ dependencies = [
|
|
|
40
41
|
"py-cpuinfo; platform_machine != 'wasm32'",
|
|
41
42
|
"requests",
|
|
42
43
|
]
|
|
43
|
-
version = "3.3.
|
|
44
|
+
version = "3.3.3"
|
|
44
45
|
|
|
45
46
|
|
|
46
47
|
[project.optional-dependencies]
|
|
@@ -110,7 +111,7 @@ extend-select = [
|
|
|
110
111
|
"RET",
|
|
111
112
|
"RUF",
|
|
112
113
|
"SIM",
|
|
113
|
-
"
|
|
114
|
+
"TC",
|
|
114
115
|
"UP",
|
|
115
116
|
]
|
|
116
117
|
ignore = [
|
|
@@ -542,6 +542,7 @@ MAX_TYPESIZE = BLOSC2_MAXTYPESIZE
|
|
|
542
542
|
MAX_BUFFERSIZE = BLOSC2_MAX_BUFFERSIZE
|
|
543
543
|
MAX_BLOCKSIZE = BLOSC2_MAXBLOCKSIZE
|
|
544
544
|
MAX_OVERHEAD = BLOSC2_MAX_OVERHEAD
|
|
545
|
+
MAX_DIM = B2ND_MAX_DIM
|
|
545
546
|
VERSION_STRING = (<char*>BLOSC2_VERSION_STRING).decode("utf-8")
|
|
546
547
|
VERSION_DATE = (<char*>BLOSC2_VERSION_DATE).decode("utf-8")
|
|
547
548
|
MIN_HEADER_LENGTH = BLOSC_MIN_HEADER_LENGTH
|
|
@@ -2391,7 +2392,7 @@ cdef class NDArray:
|
|
|
2391
2392
|
str_dtype = bytes_dtype.decode("utf-8")
|
|
2392
2393
|
try:
|
|
2393
2394
|
dtype = np.dtype(str_dtype)
|
|
2394
|
-
except TypeError:
|
|
2395
|
+
except (ValueError, TypeError):
|
|
2395
2396
|
dtype = np.dtype(ast.literal_eval(str_dtype))
|
|
2396
2397
|
self._dtype = dtype
|
|
2397
2398
|
return dtype
|
|
@@ -1164,50 +1164,58 @@ def apple_silicon_cache_size(cache_level: int) -> int:
|
|
|
1164
1164
|
return size.value
|
|
1165
1165
|
|
|
1166
1166
|
|
|
1167
|
-
def
|
|
1167
|
+
def get_cache_info(cache_level: int) -> tuple:
|
|
1168
1168
|
result = subprocess.run(["lscpu", "--json"], capture_output=True, text=True)
|
|
1169
1169
|
lscpu_info = json.loads(result.stdout)
|
|
1170
|
+
if cache_level == 0:
|
|
1171
|
+
cache_level = "1d"
|
|
1170
1172
|
for entry in lscpu_info["lscpu"]:
|
|
1171
|
-
if entry["field"] == "
|
|
1173
|
+
if entry["field"] == f"L{cache_level} cache:":
|
|
1172
1174
|
size_str, instances_str = entry["data"].split(" (")
|
|
1173
|
-
size =
|
|
1175
|
+
size, units = size_str.split()
|
|
1176
|
+
size = int(size)
|
|
1177
|
+
if units == "KiB":
|
|
1178
|
+
size *= 2**10
|
|
1179
|
+
elif units == "MiB":
|
|
1180
|
+
size *= 2**20
|
|
1181
|
+
elif units == "GiB":
|
|
1182
|
+
size *= 2**30
|
|
1183
|
+
else:
|
|
1184
|
+
raise ValueError("Unrecognized unit when guessing cache units")
|
|
1174
1185
|
instances = int(instances_str.split()[0])
|
|
1175
1186
|
return size, instances
|
|
1176
1187
|
|
|
1177
|
-
raise ValueError("
|
|
1188
|
+
raise ValueError(f"L{cache_level} cache not found in lscpu output")
|
|
1178
1189
|
|
|
1179
1190
|
|
|
1180
1191
|
def linux_cache_size(cache_level: int, default_size: int) -> int:
|
|
1181
1192
|
"""Get the data cache_level size in bytes for Linux."""
|
|
1182
1193
|
cache_size = default_size
|
|
1183
|
-
if cache_level == 3:
|
|
1184
|
-
# In modern multicore CPUs, the L3 cache is normally shared among all core complexes (CCX),
|
|
1185
|
-
# but sysfs only reports the cache size for each complex, so better use lscpu, if available.
|
|
1186
|
-
try:
|
|
1187
|
-
l3_cache_size, l3_cache_instances = get_l3_cache_info()
|
|
1188
|
-
# What comes next is a heuristic to guess the most appropriate L3 cache size.
|
|
1189
|
-
# Essentially, this is the result of different experiments, mainly on AMD CPUs
|
|
1190
|
-
# (in particular, Ryzen 9800X3D with 8 cores, and EPYC 9454P with 48 cores).
|
|
1191
|
-
# For Intel, YMMV, but my guess is that they are not using the same CCX approach.
|
|
1192
|
-
l3_cache_size *= l3_cache_instances
|
|
1193
|
-
if l3_cache_instances > 1:
|
|
1194
|
-
# This is yet another heuristic for large CPUs with core sets (CCX) having
|
|
1195
|
-
# their own L3. No idea why, but it seems to work well.
|
|
1196
|
-
l3_cache_size *= l3_cache_instances // 2
|
|
1197
|
-
return l3_cache_size
|
|
1198
|
-
except (FileNotFoundError, ValueError):
|
|
1199
|
-
# If lscpu is not available or the cache size cannot be read, try with sysfs
|
|
1200
|
-
pass
|
|
1201
1194
|
try:
|
|
1195
|
+
# Try to read the cache size from sysfs
|
|
1202
1196
|
with open(f"/sys/devices/system/cpu/cpu0/cache/index{cache_level}/size") as f:
|
|
1203
1197
|
size = f.read()
|
|
1204
1198
|
if size.endswith("K\n"):
|
|
1205
|
-
cache_size = int(size[:-2]) *
|
|
1199
|
+
cache_size = int(size[:-2]) * 2**10
|
|
1206
1200
|
elif size.endswith("M\n"):
|
|
1207
|
-
cache_size = int(size[:-2]) *
|
|
1201
|
+
cache_size = int(size[:-2]) * 2**20
|
|
1202
|
+
elif size.endswith("G\n"):
|
|
1203
|
+
cache_size = int(size[:-2]) * 2**30
|
|
1208
1204
|
except FileNotFoundError:
|
|
1209
|
-
#
|
|
1210
|
-
|
|
1205
|
+
# Try with lscpu, if available.
|
|
1206
|
+
try:
|
|
1207
|
+
cache_size, cache_instances = get_cache_info(cache_level)
|
|
1208
|
+
# cache_instances typically refers to the number of sockets, CCXs or cores,
|
|
1209
|
+
# depending on the CPU and cache level.
|
|
1210
|
+
# In general, dividing the cache size by the number of instances would bring
|
|
1211
|
+
# best performance for private caches (L1 and L2). For shared caches (L3),
|
|
1212
|
+
# this should be the case as well, but more experimentation is needed.
|
|
1213
|
+
cache_size //= cache_instances
|
|
1214
|
+
return cache_size
|
|
1215
|
+
except (FileNotFoundError, ValueError):
|
|
1216
|
+
# If lscpu is not available or the cache size cannot be read from sysfs,
|
|
1217
|
+
# return the default size.
|
|
1218
|
+
pass
|
|
1211
1219
|
return cache_size
|
|
1212
1220
|
|
|
1213
1221
|
|
|
@@ -1322,9 +1330,9 @@ def get_chunksize(blocksize, l3_minimum=4 * 2**20, l3_maximum=2**26):
|
|
|
1322
1330
|
if isinstance(l2_cache_size, int) and l3_cache_size > l2_cache_size:
|
|
1323
1331
|
chunksize = l3_cache_size
|
|
1324
1332
|
# When computing expressions, it is convenient to keep chunks for all operands
|
|
1325
|
-
# in L3 cache, so let's divide by
|
|
1333
|
+
# in L3 cache, so let's divide by 5 (4 operands + result is a typical situation
|
|
1326
1334
|
# for moderately complex expressions)
|
|
1327
|
-
chunksize //=
|
|
1335
|
+
chunksize //= 5
|
|
1328
1336
|
|
|
1329
1337
|
# Chunksize should be at least the size of L2
|
|
1330
1338
|
l2_cache_size = cpu_info.get("l2_cache_size", "Not found")
|
|
@@ -1529,7 +1537,7 @@ def compute_chunks_blocks( # noqa: C901
|
|
|
1529
1537
|
# min_blocksize = blosc2.cpu_info["l1_data_cache_size"] * 4
|
|
1530
1538
|
elif platform.system() == "Darwin" and "arm" in platform.machine():
|
|
1531
1539
|
# For Apple Silicon, experiments say we can use 4x the L1 size
|
|
1532
|
-
min_blocksize = blosc2.cpu_info["l1_data_cache_size"] *
|
|
1540
|
+
min_blocksize = blosc2.cpu_info["l1_data_cache_size"] * 4
|
|
1533
1541
|
elif "l1_data_cache_size" in blosc2.cpu_info and isinstance(
|
|
1534
1542
|
blosc2.cpu_info["l1_data_cache_size"], int
|
|
1535
1543
|
):
|
|
@@ -1562,6 +1570,11 @@ def compute_chunks_blocks( # noqa: C901
|
|
|
1562
1570
|
if chunks is None:
|
|
1563
1571
|
blocksize = math.prod(blocks) * itemsize
|
|
1564
1572
|
chunksize = get_chunksize(blocksize)
|
|
1573
|
+
# Make chunksize to be a multiple of the blocksize. This allows for:
|
|
1574
|
+
# 1. Avoid unnecessary padding in chunks
|
|
1575
|
+
# 2. Avoid exceeding the maximum buffer size (see #392)
|
|
1576
|
+
if chunksize % blocksize != 0:
|
|
1577
|
+
chunksize = chunksize // blocksize * blocksize
|
|
1565
1578
|
chunks = compute_partition(chunksize // itemsize, shape, blocks)
|
|
1566
1579
|
|
|
1567
1580
|
return tuple(chunks), tuple(blocks)
|
|
@@ -37,7 +37,7 @@ import numpy as np
|
|
|
37
37
|
import blosc2
|
|
38
38
|
from blosc2 import compute_chunks_blocks
|
|
39
39
|
from blosc2.info import InfoReporter
|
|
40
|
-
from blosc2.ndarray import _check_allowed_dtypes, get_chunks_idx, is_inside_new_expr
|
|
40
|
+
from blosc2.ndarray import _check_allowed_dtypes, get_chunks_idx, is_inside_new_expr, process_key
|
|
41
41
|
|
|
42
42
|
if not blosc2.IS_WASM:
|
|
43
43
|
import numexpr
|
|
@@ -630,6 +630,107 @@ def get_expr_operands(expression: str) -> set:
|
|
|
630
630
|
return set(visitor.operands)
|
|
631
631
|
|
|
632
632
|
|
|
633
|
+
def conserve_functions( # noqa: C901
|
|
634
|
+
expression: str,
|
|
635
|
+
operands_old: dict[str, blosc2.NDArray | blosc2.LazyExpr],
|
|
636
|
+
operands_new: dict[str, blosc2.NDArray | blosc2.LazyExpr],
|
|
637
|
+
) -> tuple(str, dict[str, blosc2.NDArray]):
|
|
638
|
+
"""
|
|
639
|
+
Given an expression in string form, return its operands.
|
|
640
|
+
|
|
641
|
+
Parameters
|
|
642
|
+
----------
|
|
643
|
+
expression : str
|
|
644
|
+
The expression in string form.
|
|
645
|
+
|
|
646
|
+
operands_old: dict[str : blosc2.ndarray | blosc2.LazyExpr]
|
|
647
|
+
Dict of operands from expression prior to eval.
|
|
648
|
+
|
|
649
|
+
operands_new: dict[str : blosc2.ndarray | blosc2.LazyExpr]
|
|
650
|
+
Dict of operands from expression after eval.
|
|
651
|
+
Returns
|
|
652
|
+
-------
|
|
653
|
+
newexpression
|
|
654
|
+
A modified string expression with the functions/constructors conserved and
|
|
655
|
+
true operands rebased and written in o- notation.
|
|
656
|
+
newoperands
|
|
657
|
+
Dict of the set of rebased operands.
|
|
658
|
+
"""
|
|
659
|
+
|
|
660
|
+
operand_to_key = {id(v): k for k, v in operands_new.items()}
|
|
661
|
+
for k, v in operands_old.items(): # extend operands_to_key with old operands
|
|
662
|
+
if isinstance(
|
|
663
|
+
v, blosc2.LazyExpr
|
|
664
|
+
): # unroll operands in LazyExpr (only necessary when have reduced a lazyexpr)
|
|
665
|
+
d = v.operands
|
|
666
|
+
else:
|
|
667
|
+
d = {k: v}
|
|
668
|
+
for newk, newv in d.items():
|
|
669
|
+
try:
|
|
670
|
+
operand_to_key[id(newv)]
|
|
671
|
+
except KeyError:
|
|
672
|
+
newk = (
|
|
673
|
+
f"o{len(operands_new)}" if newk in operands_new else newk
|
|
674
|
+
) # possible that names coincide
|
|
675
|
+
operand_to_key[id(newv)] = newk
|
|
676
|
+
operands_new[newk] = newv
|
|
677
|
+
|
|
678
|
+
class OperandVisitor(ast.NodeVisitor):
|
|
679
|
+
def __init__(self):
|
|
680
|
+
self.operandmap = {}
|
|
681
|
+
self.operands = {}
|
|
682
|
+
self.opcounter = 0
|
|
683
|
+
self.function_names = set()
|
|
684
|
+
|
|
685
|
+
def update_func(self, localop):
|
|
686
|
+
k = operand_to_key[id(localop)]
|
|
687
|
+
if k not in self.operandmap:
|
|
688
|
+
newkey = f"o{self.opcounter}"
|
|
689
|
+
self.operands[newkey] = operands_new[k]
|
|
690
|
+
self.operandmap[k] = newkey
|
|
691
|
+
self.opcounter += 1
|
|
692
|
+
return newkey
|
|
693
|
+
else:
|
|
694
|
+
return self.operandmap[k]
|
|
695
|
+
|
|
696
|
+
def visit_Name(self, node):
|
|
697
|
+
if node.id == "np": # Skip NumPy namespace (e.g. np.int8, which will be treated separately)
|
|
698
|
+
return
|
|
699
|
+
if node.id in self.function_names: # Skip function names
|
|
700
|
+
return
|
|
701
|
+
elif node.id not in dtype_symbols:
|
|
702
|
+
localop = operands_old[node.id]
|
|
703
|
+
if isinstance(localop, blosc2.LazyExpr):
|
|
704
|
+
newexpr = localop.expression
|
|
705
|
+
for (
|
|
706
|
+
opname,
|
|
707
|
+
v,
|
|
708
|
+
) in localop.operands.items(): # expression operands already in terms of basic operands
|
|
709
|
+
newopname = self.update_func(v)
|
|
710
|
+
newexpr = re.sub(
|
|
711
|
+
rf"(?<=\s){opname}|(?<=\(){opname}", newopname, newexpr
|
|
712
|
+
) # replace with newopname
|
|
713
|
+
node.id = newexpr
|
|
714
|
+
else:
|
|
715
|
+
node.id = self.update_func(localop)
|
|
716
|
+
else:
|
|
717
|
+
pass
|
|
718
|
+
self.generic_visit(node)
|
|
719
|
+
|
|
720
|
+
def visit_Call(self, node):
|
|
721
|
+
if isinstance(
|
|
722
|
+
node.func, ast.Name
|
|
723
|
+
): # visits Call first, then Name, so don't increment operandcounter yet
|
|
724
|
+
self.function_names.add(node.func.id)
|
|
725
|
+
self.generic_visit(node)
|
|
726
|
+
|
|
727
|
+
tree = ast.parse(expression)
|
|
728
|
+
visitor = OperandVisitor()
|
|
729
|
+
visitor.visit(tree)
|
|
730
|
+
newexpression, newoperands = ast.unparse(tree), visitor.operands
|
|
731
|
+
return newexpression, newoperands
|
|
732
|
+
|
|
733
|
+
|
|
633
734
|
class TransformNumpyCalls(ast.NodeTransformer):
|
|
634
735
|
def __init__(self):
|
|
635
736
|
self.replacements = {}
|
|
@@ -1481,7 +1582,8 @@ def reduce_slices( # noqa: C901
|
|
|
1481
1582
|
iter_disk = all_ndarray and any_persisted
|
|
1482
1583
|
# Experiments say that iter_disk is faster than the regular path for reductions
|
|
1483
1584
|
# even when all operands are in memory, so no need to check any_persisted
|
|
1484
|
-
# New
|
|
1585
|
+
# New benchmarks are saying the contrary (> 10% slower), so this needs more
|
|
1586
|
+
# investigation
|
|
1485
1587
|
# iter_disk = all_ndarray
|
|
1486
1588
|
else:
|
|
1487
1589
|
# WebAssembly does not support threading, so we cannot use the iter_disk option
|
|
@@ -1919,7 +2021,6 @@ class LazyExpr(LazyArray):
|
|
|
1919
2021
|
if hasattr(value2, "_where_args"):
|
|
1920
2022
|
value2 = value2.compute()
|
|
1921
2023
|
|
|
1922
|
-
self._dtype = infer_dtype(op, value1, value2)
|
|
1923
2024
|
if not isinstance(value1, LazyExpr) and not isinstance(value2, LazyExpr):
|
|
1924
2025
|
# We converted some of the operands to NDArray (where() handling above)
|
|
1925
2026
|
new_operands = {"o0": value1, "o1": value2}
|
|
@@ -2434,22 +2535,24 @@ class LazyExpr(LazyArray):
|
|
|
2434
2535
|
_globals = get_expr_globals(self.expression)
|
|
2435
2536
|
lazy_expr = eval(self.expression, _globals, self.operands)
|
|
2436
2537
|
if not isinstance(lazy_expr, blosc2.LazyExpr):
|
|
2538
|
+
key, _ = process_key(item, self.shape)
|
|
2437
2539
|
# An immediate evaluation happened (e.g. all operands are numpy arrays)
|
|
2438
2540
|
if hasattr(self, "_where_args"):
|
|
2439
2541
|
# We need to apply the where() operation
|
|
2440
2542
|
if len(self._where_args) == 1:
|
|
2441
2543
|
# We have a single argument
|
|
2442
2544
|
where_x = self._where_args["_where_x"]
|
|
2443
|
-
return where_x[:][lazy_expr]
|
|
2545
|
+
return (where_x[:][lazy_expr])[key]
|
|
2444
2546
|
if len(self._where_args) == 2:
|
|
2445
2547
|
# We have two arguments
|
|
2446
2548
|
where_x = self._where_args["_where_x"]
|
|
2447
2549
|
where_y = self._where_args["_where_y"]
|
|
2448
|
-
return np.where(lazy_expr, where_x, where_y)
|
|
2550
|
+
return np.where(lazy_expr, where_x, where_y)[key]
|
|
2449
2551
|
if hasattr(self, "_output"):
|
|
2450
2552
|
# This is not exactly optimized, but it works for now
|
|
2451
|
-
self._output[:] = lazy_expr
|
|
2452
|
-
|
|
2553
|
+
self._output[:] = lazy_expr[key]
|
|
2554
|
+
return self._output
|
|
2555
|
+
return lazy_expr[key]
|
|
2453
2556
|
|
|
2454
2557
|
return chunked_eval(lazy_expr.expression, lazy_expr.operands, item, **kwargs)
|
|
2455
2558
|
|
|
@@ -2676,10 +2779,14 @@ class LazyExpr(LazyArray):
|
|
|
2676
2779
|
_dtype = new_expr.dtype
|
|
2677
2780
|
_shape = new_expr.shape
|
|
2678
2781
|
if isinstance(new_expr, blosc2.LazyExpr):
|
|
2679
|
-
#
|
|
2680
|
-
|
|
2782
|
+
# DO NOT restore the original expression and operands
|
|
2783
|
+
# Instead rebase operands and restore only constructors
|
|
2784
|
+
expression_, operands_ = conserve_functions(
|
|
2785
|
+
_expression, _operands, new_expr.operands | local_vars
|
|
2786
|
+
)
|
|
2787
|
+
new_expr.expression = f"({expression_})" # force parenthesis
|
|
2681
2788
|
new_expr.expression_tosave = expression
|
|
2682
|
-
new_expr.operands =
|
|
2789
|
+
new_expr.operands = operands_
|
|
2683
2790
|
new_expr.operands_tosave = operands
|
|
2684
2791
|
else:
|
|
2685
2792
|
# An immediate evaluation happened (e.g. all operands are numpy arrays)
|
|
@@ -2914,6 +2914,8 @@ def _check_shape(shape):
|
|
|
2914
2914
|
shape = (shape,)
|
|
2915
2915
|
elif not isinstance(shape, tuple | list):
|
|
2916
2916
|
raise TypeError("shape should be a tuple or a list!")
|
|
2917
|
+
if len(shape) > blosc2.MAX_DIM:
|
|
2918
|
+
raise ValueError(f"shape length {len(shape)} is too large (>{blosc2.MAX_DIM})!")
|
|
2917
2919
|
return shape
|
|
2918
2920
|
|
|
2919
2921
|
|
|
@@ -3266,7 +3268,9 @@ def arange(
|
|
|
3266
3268
|
|
|
3267
3269
|
|
|
3268
3270
|
# Define a numpy linspace-like function
|
|
3269
|
-
def linspace(
|
|
3271
|
+
def linspace(
|
|
3272
|
+
start, stop, num=None, endpoint=True, dtype=np.float64, shape=None, c_order=True, **kwargs: Any
|
|
3273
|
+
):
|
|
3270
3274
|
"""Return evenly spaced numbers over a specified interval.
|
|
3271
3275
|
|
|
3272
3276
|
This is similar to `numpy.linspace` but it returns a `NDArray`
|
|
@@ -3308,8 +3312,17 @@ def linspace(start, stop, num=50, endpoint=True, dtype=np.float64, shape=None, c
|
|
|
3308
3312
|
stop_ = start_ + lout / num * (stop - start)
|
|
3309
3313
|
output[:] = np.linspace(start_, stop_, lout, endpoint=False, dtype=output.dtype)
|
|
3310
3314
|
|
|
3311
|
-
if
|
|
3312
|
-
shape
|
|
3315
|
+
if shape is None or num is None:
|
|
3316
|
+
if shape is None and num is None:
|
|
3317
|
+
raise ValueError("Either `shape` or `num` must be specified.")
|
|
3318
|
+
if shape is None: # num is not None
|
|
3319
|
+
shape = (num,)
|
|
3320
|
+
else: # num is none
|
|
3321
|
+
num = math.prod(shape)
|
|
3322
|
+
|
|
3323
|
+
# check compatibility of shape and num
|
|
3324
|
+
if math.prod(shape) != num:
|
|
3325
|
+
raise ValueError("The specified shape is not consistent with the specified num value")
|
|
3313
3326
|
dtype = _check_dtype(dtype)
|
|
3314
3327
|
|
|
3315
3328
|
if is_inside_new_expr():
|
|
@@ -3624,17 +3637,22 @@ def asarray(array: np.ndarray | blosc2.C2Array, **kwargs: Any) -> NDArray:
|
|
|
3624
3637
|
|
|
3625
3638
|
|
|
3626
3639
|
def _check_ndarray_kwargs(**kwargs): # noqa: C901
|
|
3627
|
-
|
|
3640
|
+
storage = kwargs.get("storage")
|
|
3641
|
+
if storage is not None:
|
|
3628
3642
|
for key in kwargs:
|
|
3629
3643
|
if key in list(blosc2.Storage.__annotations__):
|
|
3630
3644
|
raise AttributeError(
|
|
3631
3645
|
"Cannot pass both `storage` and other kwargs already included in Storage"
|
|
3632
3646
|
)
|
|
3633
|
-
storage = kwargs.get("storage")
|
|
3634
3647
|
if isinstance(storage, blosc2.Storage):
|
|
3635
3648
|
kwargs = {**kwargs, **asdict(storage)}
|
|
3636
3649
|
else:
|
|
3637
3650
|
kwargs = {**kwargs, **storage}
|
|
3651
|
+
else:
|
|
3652
|
+
# Add the default storage values as long as they are not already passed
|
|
3653
|
+
storage_dflts = asdict(blosc2.Storage(urlpath=kwargs.get("urlpath"))) # urlpath can affect defaults
|
|
3654
|
+
not_passed = {k: v for k, v in storage_dflts.items() if k not in kwargs}
|
|
3655
|
+
kwargs = {**kwargs, **not_passed}
|
|
3638
3656
|
|
|
3639
3657
|
supported_keys = [
|
|
3640
3658
|
"chunks",
|
|
@@ -3871,11 +3889,11 @@ def matmul(x1: NDArray, x2: NDArray, **kwargs: Any) -> NDArray:
|
|
|
3871
3889
|
r = x2.chunks[-1]
|
|
3872
3890
|
|
|
3873
3891
|
for row in range(0, n, p):
|
|
3874
|
-
row_end = (row + p
|
|
3892
|
+
row_end = builtins.min(row + p, n)
|
|
3875
3893
|
for col in range(0, m, q):
|
|
3876
|
-
col_end = (col + q
|
|
3894
|
+
col_end = builtins.min(col + q, m)
|
|
3877
3895
|
for aux in range(0, k, r):
|
|
3878
|
-
aux_end = (aux + r
|
|
3896
|
+
aux_end = builtins.min(aux + r, k)
|
|
3879
3897
|
bx1 = x1[row:row_end, aux:aux_end]
|
|
3880
3898
|
bx2 = x2[aux:aux_end, col:col_end]
|
|
3881
3899
|
result[row:row_end, col:col_end] += np.matmul(bx1, bx2)
|
|
@@ -3946,6 +3964,7 @@ def permute_dims(arr: NDArray, axes: tuple[int] | list[int] | None = None, **kwa
|
|
|
3946
3964
|
[[13, 14, 15, 16],
|
|
3947
3965
|
[17, 18, 19, 20],
|
|
3948
3966
|
[21, 22, 23, 24]]])
|
|
3967
|
+
|
|
3949
3968
|
>>> at = blosc2.permute_dims(a, axes=(1, 0, 2))
|
|
3950
3969
|
>>> at[:]
|
|
3951
3970
|
array([[[ 1, 2, 3, 4],
|
|
@@ -3955,37 +3974,39 @@ def permute_dims(arr: NDArray, axes: tuple[int] | list[int] | None = None, **kwa
|
|
|
3955
3974
|
[[ 9, 10, 11, 12],
|
|
3956
3975
|
[21, 22, 23, 24]]])
|
|
3957
3976
|
"""
|
|
3958
|
-
|
|
3959
3977
|
if np.isscalar(arr) or arr.ndim < 2:
|
|
3960
3978
|
return arr
|
|
3961
3979
|
|
|
3980
|
+
ndim = arr.ndim
|
|
3981
|
+
|
|
3962
3982
|
if axes is None:
|
|
3963
|
-
axes = range(
|
|
3983
|
+
axes = tuple(range(ndim))[::-1]
|
|
3964
3984
|
else:
|
|
3965
|
-
|
|
3966
|
-
if sorted(
|
|
3967
|
-
raise ValueError(f"axes {axes} is not a valid permutation of {
|
|
3968
|
-
axes = axes_transformed
|
|
3985
|
+
axes = tuple(axis if axis >= 0 else ndim + axis for axis in axes)
|
|
3986
|
+
if sorted(axes) != list(range(ndim)):
|
|
3987
|
+
raise ValueError(f"axes {axes} is not a valid permutation of {ndim} dimensions")
|
|
3969
3988
|
|
|
3970
3989
|
new_shape = tuple(arr.shape[axis] for axis in axes)
|
|
3971
|
-
if "chunks" not in kwargs:
|
|
3990
|
+
if "chunks" not in kwargs or kwargs["chunks"] is None:
|
|
3972
3991
|
kwargs["chunks"] = tuple(arr.chunks[axis] for axis in axes)
|
|
3973
3992
|
|
|
3974
3993
|
result = blosc2.empty(shape=new_shape, dtype=arr.dtype, **kwargs)
|
|
3975
3994
|
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3995
|
+
chunks = arr.chunks
|
|
3996
|
+
shape = arr.shape
|
|
3997
|
+
|
|
3998
|
+
for info in arr.iterchunks_info():
|
|
3999
|
+
coords = info.coords
|
|
4000
|
+
start_stop = [
|
|
4001
|
+
(coord * chunk, builtins.min(chunk * (coord + 1), dim))
|
|
4002
|
+
for coord, chunk, dim in zip(coords, chunks, shape, strict=False)
|
|
4003
|
+
]
|
|
3980
4004
|
|
|
3981
|
-
|
|
3982
|
-
|
|
4005
|
+
src_slice = tuple(slice(start, stop) for start, stop in start_stop)
|
|
4006
|
+
dst_slice = tuple(slice(start_stop[ax][0], start_stop[ax][1]) for ax in axes)
|
|
3983
4007
|
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
block = arr[block_slices]
|
|
3987
|
-
target_slices = tuple(block_slices[axis] for axis in axes)
|
|
3988
|
-
result[target_slices] = np.transpose(block, axes=axes).copy()
|
|
4008
|
+
transposed = np.transpose(arr[src_slice], axes=axes)
|
|
4009
|
+
result[dst_slice] = np.ascontiguousarray(transposed)
|
|
3989
4010
|
|
|
3990
4011
|
return result
|
|
3991
4012
|
|
|
@@ -4019,7 +4040,7 @@ def transpose(x, **kwargs: Any) -> NDArray:
|
|
|
4019
4040
|
stacklevel=2,
|
|
4020
4041
|
)
|
|
4021
4042
|
|
|
4022
|
-
# If arguments are dimension < 2 they are returned
|
|
4043
|
+
# If arguments are dimension < 2, they are returned
|
|
4023
4044
|
if np.isscalar(x) or x.ndim < 2:
|
|
4024
4045
|
return x
|
|
4025
4046
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.3.3"
|
|
@@ -27,7 +27,7 @@ def sample_data(request):
|
|
|
27
27
|
# The jit decorator can work with any numpy or NDArray params in functions
|
|
28
28
|
a = blosc2.linspace(0, 1, shape[0] * shape[1], dtype=dtype, shape=shape)
|
|
29
29
|
b = np.linspace(1, 2, shape[0] * shape[1], dtype=dtype).reshape(shape)
|
|
30
|
-
c = blosc2.linspace(-10, 10, cshape
|
|
30
|
+
c = blosc2.linspace(-10, 10, np.prod(cshape), dtype=dtype, shape=cshape)
|
|
31
31
|
return a, b, c, shape
|
|
32
32
|
|
|
33
33
|
|
|
@@ -26,7 +26,7 @@ def sample_data(request):
|
|
|
26
26
|
# The jit decorator can work with any numpy or NDArray params in functions
|
|
27
27
|
a = blosc2.linspace(0, 1, shape[0] * shape[1], dtype=dtype, shape=shape)
|
|
28
28
|
b = np.linspace(1, 2, shape[0] * shape[1], dtype=dtype).reshape(shape)
|
|
29
|
-
c = blosc2.linspace(-10, 10, cshape
|
|
29
|
+
c = blosc2.linspace(-10, 10, np.prod(cshape), dtype=dtype, shape=cshape)
|
|
30
30
|
return a, b, c, shape
|
|
31
31
|
|
|
32
32
|
|