blosc2 3.3.4__tar.gz → 3.4.0__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.4 → blosc2-3.4.0}/.pre-commit-config.yaml +1 -1
- {blosc2-3.3.4 → blosc2-3.4.0}/ANNOUNCE.rst +2 -6
- {blosc2-3.3.4 → blosc2-3.4.0}/CMakeLists.txt +1 -1
- {blosc2-3.3.4 → blosc2-3.4.0}/PKG-INFO +1 -1
- {blosc2-3.3.4 → blosc2-3.4.0}/README_DEVELOPERS.md +14 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/RELEASE_NOTES.md +14 -2
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/python-blosc2.rst +1 -1
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/ndarray.rst +1 -0
- blosc2-3.4.0/examples/blosc2_hdf5_compression.py +95 -0
- blosc2-3.4.0/examples/ndarray/lazyexpr_where_indexing.py +42 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/pyproject.toml +1 -1
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/__init__.py +1 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/blosc2_ext.pyx +25 -0
- blosc2-3.4.0/src/blosc2/exceptions.py +7 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/lazyexpr.py +55 -32
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/ndarray.py +67 -2
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/proxy.py +55 -0
- blosc2-3.4.0/src/blosc2/version.py +1 -0
- blosc2-3.4.0/tests/ndarray/test_concatenate.py +64 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lazyexpr.py +44 -11
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lazyexpr_fields.py +50 -10
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_reductions.py +14 -1
- blosc2-3.4.0/tests/test_pandas_udf_engine.py +120 -0
- blosc2-3.3.4/src/blosc2/version.py +0 -1
- {blosc2-3.3.4 → blosc2-3.4.0}/.gitignore +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/.guix/modules/python-blosc2-package.scm +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/.guix-channel +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/CONTRIBUTING.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/LICENSE.txt +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/README.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/RELEASING.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/code_of_conduct.md +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-favicon_32x32.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-favicon_64x64.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-logo_128.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-logo_256.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/css/custom.css +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/conf.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/development/code-of-conduct.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/development/contributing.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/development/index.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/index.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/installation.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/overview.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/01.ndarray-basics.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/02.lazyarray-expressions.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/03.lazyarray-udf.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/04.reductions.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/05.persistent-reductions.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/06.remote_proxy.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/07.schunk-basics.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/08.schunk-slicing_and_beyond.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/10.ucodecs-ufilters.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/11.prefilters.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/12.postfilters.ipynb +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/blosc2-pipeline.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/blosc2-pipeline.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/lazyexpr-broadcast.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/3D-cube-plane.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/3D-cube.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/memory-access-2D-x.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/memory-access-2D-y.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/remote_proxy.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/backward.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/backward.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder2.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder2.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder2.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder2.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/forward.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/forward.svg +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/index.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/array_operations.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__getitem__.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__init__.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__len__.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__setitem__.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.append_data.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.decompress_chunk.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.delete_chunk.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.fill_special.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.filler.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.get_chunk.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.get_slice.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.insert_chunk.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.insert_data.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.iterchunks.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.iterchunks_info.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.postfilter.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.prefilter.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.remove_postfilter.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.remove_prefilter.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.to_cframe.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.update_chunk.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.update_data.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/c2array.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/classes.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/decorators.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/index.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/lazy_functions.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/lazyarray.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/linear_algebra.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/low_level.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/ndfield.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/proxy.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/proxyndsource.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/proxysource.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/reduction_functions.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/save_load.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/schunk.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/simpleproxy.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/storage.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/utilities.rst +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/doc/release_notes/index.md +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/btune.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/c2array-get-slice.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/compress2_decompress2.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/compress_decompress.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/filler.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/gil.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/mmap-rw.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/arange-constructor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/asarray_.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/broadcast_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/buffer.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/bytedelta_filter.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/c2array_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_fields.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_udf_numba.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_where.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/copy_.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/empty_.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/eye-constructor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/filter_sort_fields.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/formats.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/fromiter-constructor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/general_expressions.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/getitem.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/iterchunks_info.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/jit-expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/jit-numpy-funcs.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/jit-reduc.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/linspace-constructor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/lists-vs-bools-idx.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/meta.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/ndarray_copy.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/ndmean.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/persistency.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/proxy-carray.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/proxy-ndarray.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_and_enlarge.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_expr_save.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_string_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/resize_.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/work_with_numpy.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/zfp_codec.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/pack_array.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/pack_tensor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/postfilter1.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/postfilter2.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/postfilter3.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/prefilter.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/save_tensor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/schunk.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/schunk_roundtrip.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ucodecs.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/ufilters.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/examples/vlmeta.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/generate_version.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/guix.scm +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/Complete-Write-Read-B2ND.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/M1-i386-vs-arm64-pack.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/M1-i386-vs-arm64-unpack.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/Read-Partial-Slices-B2ND.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/b2nd-2level-parts.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/eval-expr-full-mem-M2.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/eval-expr-scarce-mem-M2.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-dask-large.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-dask-small.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-expr-large.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-expr.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/linspace-compress.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/linspace-decompress.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/pack-array-cratios.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/reduc-float64-amd.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/images/reduc-float64-log-amd.png +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/pytest.ini +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/c2array.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/core.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/helpers.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/info.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/schunk.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/storage.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/conftest.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_auto_parts.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_buffer.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_c2array_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_c2array_reductions.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_c2array_udf.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_copy.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_empty.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_evaluate.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_full.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_get_slice_nchunks.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_getitem.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_iterchunks_info.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_jit.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lazyudf.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lossy.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_matmul.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_metalayers.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_mode.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_nans.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_ndarray.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_numpy.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_persistency.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_proxy.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_proxy_c2array.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_proxy_expr.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_resize.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_setitem.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_slice.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_squeeze.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_struct_dtype.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_transpose.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_zeros.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_bytes_array.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_comp_info.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_compress2.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_compression_parameters.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_compressors.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_decompress.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_iterchunks.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_mmap.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_open.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_open_c2array.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_pathlib.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_postfilters.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_prefilters.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_proxy_schunk.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_python_blosc.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_constructor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_delete.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_get_slice.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_get_slice_nchunks.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_insert.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_set_slice.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_update.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_storage.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_tensor.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_ucodecs.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_ufilters.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_vlmeta.py +0 -0
- {blosc2-3.3.4 → blosc2-3.4.0}/update_version.py +0 -0
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
Announcing Python-Blosc2 3.
|
|
1
|
+
Announcing Python-Blosc2 3.4.0
|
|
2
2
|
==============================
|
|
3
3
|
|
|
4
|
-
This
|
|
5
|
-
correct chaining of *string* lazy expressions (to allow operands with more
|
|
6
|
-
diverse data types). In addition, both indexing and where expressions are now
|
|
7
|
-
supported within *string* lazy expressions. Finally, casting rules have
|
|
8
|
-
been improved to be more consistent with NumPy.
|
|
4
|
+
This release adds significant new functionality in the form of ``concatenate``. We support general concatenation of ndarrays, and offer an optimised path with significant speedups for the case of concatenating arrays with compatible chunk and blockshapes. In addition, there are bug fixes and more functionality for slicing of lazyexprs, and the possibility to jit compile user-defined functions which operate on pandas objects using the blosc2 engine.
|
|
9
5
|
|
|
10
6
|
You can think of Python-Blosc2 3.x as an extension of NumPy/numexpr that:
|
|
11
7
|
|
|
@@ -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 1c2f8bb0c914c43e23b751fbcf6642cd7aec09db # v2.18.0 (concatenate added)
|
|
54
54
|
)
|
|
55
55
|
FetchContent_MakeAvailable(blosc2)
|
|
56
56
|
include_directories("${blosc2_SOURCE_DIR}/include")
|
|
@@ -22,6 +22,20 @@ You are done!
|
|
|
22
22
|
pip install . # add -e for editable mode
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
There are situations where you may want to build the C-Blosc2 library separately, for example, when debugging issues in the C library. In that case, let's assume you have the C-Blosc2 library installed in `/usr/local`:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
CMAKE_PREFIX_PATH=/usr/local USE_SYSTEM_BLOSC2=1 pip install -e .
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
and then, you can run the tests with:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
LD_LIBRARY_PATH=/usr/local/lib pytest
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
[replace `LD_LIBRARY_PATH` with the appropriate environment variable for your system, such as `DYLD_LIBRARY_PATH` on macOS or `PATH` on Windows, if necessary].
|
|
38
|
+
|
|
25
39
|
That's it! You can now proceed to the testing section.
|
|
26
40
|
|
|
27
41
|
## Testing
|
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
# Release notes
|
|
2
|
-
|
|
3
|
-
## Changes from 3.3.4 to 3.3.5
|
|
2
|
+
## Changes from 3.4.0 to 3.4.1
|
|
4
3
|
|
|
5
4
|
XXX version-specific blurb XXX
|
|
6
5
|
|
|
6
|
+
## Changes from 3.3.4 to 3.4.0
|
|
7
|
+
|
|
8
|
+
* Added C-level ``concatenate`` function in response to community request. When possible, uses an optimised path which avoids decompression and recompression, giving a significant performance boost. See PR #423.
|
|
9
|
+
|
|
10
|
+
* Slicing has been added to string-based lazyexprs, so that one may use
|
|
11
|
+
expressions like `expr[1:3] +1` to compute a slice of the expression. This is useful
|
|
12
|
+
for getting a sub-expression of a larger expression, and it works with both
|
|
13
|
+
string-based and lazy expressions. See PR #417.
|
|
14
|
+
|
|
15
|
+
* Relatedly, the behaviour of the `slice` parameter in the `compute()` method of `LazyExpr` has been made more consistent and is now better documented, so that results are as expected. See PR #419.
|
|
16
|
+
|
|
17
|
+
* UDF support for pandas has been added to allow for the use of ``blosc2.jit``. See PR #418. Thanks to [@datapythonista](https://github.com/datapythonista) for the implementation!
|
|
18
|
+
|
|
7
19
|
## Changes from 3.3.3 to 3.3.4
|
|
8
20
|
|
|
9
21
|
* Expand possibilities for chaining string-based lazy expressions to incorporate
|
|
@@ -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.4 released on 2025-05-22!</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>
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
#######################################################################
|
|
2
|
+
# Copyright (c) 2019-present, Blosc Development Team <blosc@blosc.org>
|
|
3
|
+
# All rights reserved.
|
|
4
|
+
#
|
|
5
|
+
# This source code is licensed under a BSD-style license (found in the
|
|
6
|
+
# LICENSE file in the root directory of this source tree)
|
|
7
|
+
#######################################################################
|
|
8
|
+
|
|
9
|
+
# This shows how to convert a generic .h5 file to a custom blosc2-compressed .h5 file
|
|
10
|
+
# The blosc2 plugin in hdf5plugin doesn't support custom block shapes, and so one
|
|
11
|
+
# has to go a different route for more bespoke compression
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
|
|
15
|
+
import h5py
|
|
16
|
+
import hdf5plugin
|
|
17
|
+
|
|
18
|
+
import blosc2
|
|
19
|
+
|
|
20
|
+
clevel = 5 # compression level, e.g., 0-9, where 0 is no compression and 9 is maximum compression
|
|
21
|
+
fname_in = "kevlar.h5" # input file with the kevlar dataset
|
|
22
|
+
fname_out = "kevlar-blosc2.h5"
|
|
23
|
+
if not os.path.exists(fname_in):
|
|
24
|
+
raise FileNotFoundError(
|
|
25
|
+
f"Input file {fname_in} does not exist\n"
|
|
26
|
+
"Please download it from the kevlar repository at:"
|
|
27
|
+
" http://www.silx.org/pub/pyFAI/pyFAI_UM_2020/data_ID13/kevlar.h5"
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
# Example 1
|
|
31
|
+
# hdf5plugin supports limited blosc2 compression with certain codecs
|
|
32
|
+
cname = "zstd"
|
|
33
|
+
with h5py.File(fname_in, "r") as fr:
|
|
34
|
+
dset = fr["/entry/data/data"][:]
|
|
35
|
+
with h5py.File(fname_out, "w") as fw:
|
|
36
|
+
g = fw.create_group("/data")
|
|
37
|
+
b2comp = hdf5plugin.Blosc2(cname=cname, clevel=clevel, filters=hdf5plugin.Blosc2.BITSHUFFLE)
|
|
38
|
+
dset_out = g.create_dataset(
|
|
39
|
+
f"cname-{cname}",
|
|
40
|
+
data=dset,
|
|
41
|
+
dtype=dset.dtype,
|
|
42
|
+
chunks=(1,) + dset.shape[1:], # chunk size of 1 frame
|
|
43
|
+
**b2comp,
|
|
44
|
+
)
|
|
45
|
+
print("Successfully compressed file with hdf5plugin")
|
|
46
|
+
|
|
47
|
+
# Example 2
|
|
48
|
+
# For other codecs (e.g grok) or for more custom compression such as with user-defined block shapes, one
|
|
49
|
+
# has to use a more involved route
|
|
50
|
+
blocks = (50, 80, 80)
|
|
51
|
+
chunks = (200, 240, 240)
|
|
52
|
+
cparams = {
|
|
53
|
+
"codec": blosc2.Codec.LZ4,
|
|
54
|
+
"filters": [blosc2.Filter.BITSHUFFLE],
|
|
55
|
+
"splitmode": blosc2.SplitMode.NEVER_SPLIT,
|
|
56
|
+
"clevel": clevel,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if os.path.exists("dset.b2nd"): # don't reload dset to blosc2 if already done so once
|
|
60
|
+
b2im = blosc2.open(urlpath="dset.b2nd", mode="r")
|
|
61
|
+
s, d = b2im.shape, b2im.dtype
|
|
62
|
+
else:
|
|
63
|
+
with h5py.File(fname_in, "r") as fr: # load file and process to blosc2 array
|
|
64
|
+
dset = fr["/entry/data/data"][:]
|
|
65
|
+
b2im = blosc2.asarray(
|
|
66
|
+
dset, chunks=chunks, blocks=blocks, cparams=cparams, urlpath="dset.b2nd", mode="w"
|
|
67
|
+
)
|
|
68
|
+
d = dset.dtype
|
|
69
|
+
del dset
|
|
70
|
+
|
|
71
|
+
# Write to .h5 file #
|
|
72
|
+
with h5py.File(fname_out, "w") as fw:
|
|
73
|
+
g = fw.create_group("/data")
|
|
74
|
+
b2comp = hdf5plugin.Blosc2() # just for identification, no compression algorithm specified
|
|
75
|
+
dset_out = g.create_dataset(
|
|
76
|
+
"cname-customlz4",
|
|
77
|
+
s,
|
|
78
|
+
d,
|
|
79
|
+
chunks=chunks, # chunk size of 1 frame
|
|
80
|
+
**b2comp,
|
|
81
|
+
)
|
|
82
|
+
# Write individual blosc2 chunks directly to hdf5
|
|
83
|
+
# hdf5 requires a cframe, which is only available via blosc2 schunks (not chunks)
|
|
84
|
+
for info in b2im.iterchunks_info():
|
|
85
|
+
ncoords = tuple(n * chunks[i] for i, n in enumerate(info.coords))
|
|
86
|
+
aux = blosc2.empty(
|
|
87
|
+
shape=b2im.chunks, chunks=b2im.chunks, blocks=b2im.blocks, dtype=b2im.dtype
|
|
88
|
+
) # very cheap memory allocation
|
|
89
|
+
aux.schunk.insert_chunk(
|
|
90
|
+
0, b2im.get_chunk(info.nchunk)
|
|
91
|
+
) # insert chunk into blosc2 array so we have schunk wrapper (no decompression required)
|
|
92
|
+
dset_out.id.write_direct_chunk(
|
|
93
|
+
ncoords, aux.schunk.to_cframe()
|
|
94
|
+
) # convert schunk to cframe and write to hdf5
|
|
95
|
+
print("Successfully compressed file with custom parameters")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Imports
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
import blosc2
|
|
6
|
+
|
|
7
|
+
N = 1000
|
|
8
|
+
it = ((-x + 1, x - 2, 0.1 * x) for x in range(N))
|
|
9
|
+
sa = blosc2.fromiter(
|
|
10
|
+
it, dtype=[("A", "i4"), ("B", "f4"), ("C", "f8")], shape=(N,), urlpath="sa-1M.b2nd", mode="w"
|
|
11
|
+
)
|
|
12
|
+
expr = sa["(A < B)"]
|
|
13
|
+
A = sa["A"][:]
|
|
14
|
+
B = sa["B"][:]
|
|
15
|
+
C = sa["C"][:]
|
|
16
|
+
temp = sa[:]
|
|
17
|
+
indices = A < B
|
|
18
|
+
idx = np.argmax(indices)
|
|
19
|
+
|
|
20
|
+
# One might think that expr[:10] gives the first 10 elements of the evaluated expression, but this is not the case.
|
|
21
|
+
# It actually computes the expression on the first 10 elements of the operands; since for some elements the condition
|
|
22
|
+
# is False, the result will be shorter than 10 elements.
|
|
23
|
+
# Returns less than 10 elements in general
|
|
24
|
+
sliced = expr.compute(slice(0, 10))
|
|
25
|
+
gotitem = expr[:10]
|
|
26
|
+
np.testing.assert_array_equal(sliced[:], gotitem)
|
|
27
|
+
np.testing.assert_array_equal(gotitem, temp[:10][indices[:10]]) # Equivalent syntax
|
|
28
|
+
# Actually this makes sense since one can understand this as a request to compute on a portion of operands.
|
|
29
|
+
# If one desires a portion of the result, one should compute the whole expression and then slice it.
|
|
30
|
+
|
|
31
|
+
# Get first element for which condition is true
|
|
32
|
+
sliced = expr.compute(idx)
|
|
33
|
+
gotitem = expr[idx]
|
|
34
|
+
# Arrays of one element
|
|
35
|
+
np.testing.assert_array_equal(sliced[()], gotitem)
|
|
36
|
+
np.testing.assert_array_equal(gotitem, temp[idx])
|
|
37
|
+
|
|
38
|
+
# Should return void arrays here.
|
|
39
|
+
sliced = expr.compute(0)
|
|
40
|
+
gotitem = expr[0]
|
|
41
|
+
np.testing.assert_array_equal(sliced[()], gotitem)
|
|
42
|
+
np.testing.assert_array_equal(gotitem, temp[0])
|
|
@@ -507,6 +507,8 @@ cdef extern from "b2nd.h":
|
|
|
507
507
|
int b2nd_squeeze_index(b2nd_array_t *array, const c_bool *index)
|
|
508
508
|
int b2nd_resize(b2nd_array_t *array, const int64_t *new_shape, const int64_t *start)
|
|
509
509
|
int b2nd_copy(b2nd_context_t *ctx, b2nd_array_t *src, b2nd_array_t **array)
|
|
510
|
+
int b2nd_concatenate(b2nd_context_t *ctx, b2nd_array_t *src1, b2nd_array_t *src2,
|
|
511
|
+
int8_t axis, c_bool copy, b2nd_array_t **array)
|
|
510
512
|
int b2nd_from_schunk(blosc2_schunk *schunk, b2nd_array_t **array)
|
|
511
513
|
|
|
512
514
|
void blosc2_unidim_to_multidim(uint8_t ndim, int64_t *shape, int64_t i, int64_t *index)
|
|
@@ -2867,3 +2869,26 @@ def schunk_get_slice_nchunks(schunk: SChunk, key):
|
|
|
2867
2869
|
res[i] = chunks_idx[i]
|
|
2868
2870
|
free(chunks_idx)
|
|
2869
2871
|
return res
|
|
2872
|
+
|
|
2873
|
+
|
|
2874
|
+
def concatenate(arr1: NDArray, arr2: NDArray, axis: int, **kwargs):
|
|
2875
|
+
"""
|
|
2876
|
+
Concatenate two NDArray objects along a specified axis.
|
|
2877
|
+
"""
|
|
2878
|
+
cdef c_bool copy = kwargs.pop("copy", True)
|
|
2879
|
+
cdef b2nd_context_t *ctx = create_b2nd_context(arr1.shape, arr1.chunks, arr1.blocks, arr1.dtype, kwargs)
|
|
2880
|
+
if ctx == NULL:
|
|
2881
|
+
raise RuntimeError("Error while creating the context for concatenation")
|
|
2882
|
+
|
|
2883
|
+
cdef b2nd_array_t *array
|
|
2884
|
+
_check_rc(b2nd_concatenate(ctx, arr1.array, arr2.array, axis, copy, &array),
|
|
2885
|
+
"Error while concatenating the arrays")
|
|
2886
|
+
_check_rc(b2nd_free_ctx(ctx), "Error while freeing the context")
|
|
2887
|
+
|
|
2888
|
+
if copy:
|
|
2889
|
+
# We have copied the concatenated data into a new array
|
|
2890
|
+
return blosc2.NDArray(_schunk=PyCapsule_New(array.sc, <char *> "blosc2_schunk*", NULL),
|
|
2891
|
+
_array=PyCapsule_New(array, <char *> "b2nd_array_t*", NULL))
|
|
2892
|
+
else:
|
|
2893
|
+
# Return the first array, which now contains the concatenated data
|
|
2894
|
+
return arr1
|
|
@@ -10,6 +10,7 @@ from __future__ import annotations
|
|
|
10
10
|
|
|
11
11
|
import ast
|
|
12
12
|
import asyncio
|
|
13
|
+
import builtins
|
|
13
14
|
import concurrent.futures
|
|
14
15
|
import copy
|
|
15
16
|
import inspect
|
|
@@ -28,6 +29,8 @@ from typing import TYPE_CHECKING, Any
|
|
|
28
29
|
|
|
29
30
|
from numpy.exceptions import ComplexWarning
|
|
30
31
|
|
|
32
|
+
from . import exceptions
|
|
33
|
+
|
|
31
34
|
if TYPE_CHECKING:
|
|
32
35
|
from collections.abc import Callable, Sequence
|
|
33
36
|
|
|
@@ -277,8 +280,9 @@ class LazyArray(ABC):
|
|
|
277
280
|
Parameters
|
|
278
281
|
----------
|
|
279
282
|
item: slice, list of slices, optional
|
|
280
|
-
If
|
|
281
|
-
|
|
283
|
+
If provided, item is used to slice the operands *prior* to computation; not to retrieve specified slices of
|
|
284
|
+
the evaluated result. This difference between slicing operands and slicing the final expression
|
|
285
|
+
is important when reductions or a where clause are used in the expression.
|
|
282
286
|
|
|
283
287
|
kwargs: Any, optional
|
|
284
288
|
Keyword arguments that are supported by the :func:`empty` constructor.
|
|
@@ -327,7 +331,9 @@ class LazyArray(ABC):
|
|
|
327
331
|
Parameters
|
|
328
332
|
----------
|
|
329
333
|
item: int, slice or sequence of slices
|
|
330
|
-
|
|
334
|
+
If provided, item is used to slice the operands *prior* to computation; not to retrieve specified slices of
|
|
335
|
+
the evaluated result. This difference between slicing operands and slicing the final expression
|
|
336
|
+
is important when reductions or a where clause are used in the expression.
|
|
331
337
|
|
|
332
338
|
Returns
|
|
333
339
|
-------
|
|
@@ -465,6 +471,10 @@ class LazyArray(ABC):
|
|
|
465
471
|
"version": 3,
|
|
466
472
|
}
|
|
467
473
|
|
|
474
|
+
# Provide a way to serialize the LazyArray
|
|
475
|
+
def to_cframe(self):
|
|
476
|
+
return self.compute().to_cframe()
|
|
477
|
+
|
|
468
478
|
|
|
469
479
|
def convert_inputs(inputs):
|
|
470
480
|
if not inputs or len(inputs) == 0:
|
|
@@ -1373,7 +1383,8 @@ def slices_eval( # noqa: C901
|
|
|
1373
1383
|
for i, (c, s) in enumerate(zip(coords, chunks, strict=True))
|
|
1374
1384
|
)
|
|
1375
1385
|
# Check whether current slice_ intersects with _slice
|
|
1376
|
-
|
|
1386
|
+
checker = _slice.item() if hasattr(_slice, "item") else _slice # can't use != when _slice is np.int
|
|
1387
|
+
if checker is not None and checker != ():
|
|
1377
1388
|
# Ensure that _slice is of type slice
|
|
1378
1389
|
key = ndindex.ndindex(_slice).expand(shape).raw
|
|
1379
1390
|
_slice = tuple(k if isinstance(k, slice) else slice(k, k + 1, None) for k in key)
|
|
@@ -1503,19 +1514,7 @@ def slices_eval( # noqa: C901
|
|
|
1503
1514
|
else:
|
|
1504
1515
|
raise ValueError("The where condition must be a tuple with one or two elements")
|
|
1505
1516
|
|
|
1506
|
-
if
|
|
1507
|
-
if isinstance(out, np.ndarray):
|
|
1508
|
-
out = out[orig_slice]
|
|
1509
|
-
if _order is not None:
|
|
1510
|
-
indices_ = indices_[orig_slice]
|
|
1511
|
-
elif isinstance(out, blosc2.NDArray):
|
|
1512
|
-
# It *seems* better to choose an automatic chunks and blocks for the output array
|
|
1513
|
-
# out = out.slice(orig_slice, chunks=out.chunks, blocks=out.blocks)
|
|
1514
|
-
out = out.slice(orig_slice)
|
|
1515
|
-
else:
|
|
1516
|
-
raise ValueError("The output array is not a NumPy array or a NDArray")
|
|
1517
|
-
|
|
1518
|
-
if where is not None and len(where) < 2:
|
|
1517
|
+
if where is not None and len(where) < 2: # Don't need to take orig_slice since filled up from 0 index
|
|
1519
1518
|
if _order is not None:
|
|
1520
1519
|
# argsort the result following _order
|
|
1521
1520
|
new_order = np.argsort(out[:lenout])
|
|
@@ -1527,6 +1526,19 @@ def slices_eval( # noqa: C901
|
|
|
1527
1526
|
else:
|
|
1528
1527
|
out.resize((lenout,))
|
|
1529
1528
|
|
|
1529
|
+
else: # Need to take orig_slice since filled up array according to slice_ for each chunk
|
|
1530
|
+
if orig_slice is not None:
|
|
1531
|
+
if isinstance(out, np.ndarray):
|
|
1532
|
+
out = out[orig_slice]
|
|
1533
|
+
if _order is not None:
|
|
1534
|
+
indices_ = indices_[orig_slice]
|
|
1535
|
+
elif isinstance(out, blosc2.NDArray):
|
|
1536
|
+
# It *seems* better to choose an automatic chunks and blocks for the output array
|
|
1537
|
+
# out = out.slice(orig_slice, chunks=out.chunks, blocks=out.blocks)
|
|
1538
|
+
out = out.slice(orig_slice)
|
|
1539
|
+
else:
|
|
1540
|
+
raise ValueError("The output array is not a NumPy array or a NDArray")
|
|
1541
|
+
|
|
1530
1542
|
return out
|
|
1531
1543
|
|
|
1532
1544
|
|
|
@@ -1822,7 +1834,8 @@ def chunked_eval( # noqa: C901
|
|
|
1822
1834
|
operands: dict
|
|
1823
1835
|
A dictionary containing the operands for the expression.
|
|
1824
1836
|
item: int, slice or sequence of slices, optional
|
|
1825
|
-
The slice(s) to be
|
|
1837
|
+
The slice(s) of the operands to be used in computation. Note that step parameter is not honored yet.
|
|
1838
|
+
Item is used to slice the operands PRIOR to computation.
|
|
1826
1839
|
kwargs: Any, optional
|
|
1827
1840
|
Additional keyword arguments supported by the :func:`empty` constructor. In addition,
|
|
1828
1841
|
the following keyword arguments are supported:
|
|
@@ -2597,7 +2610,7 @@ class LazyExpr(LazyArray):
|
|
|
2597
2610
|
_globals = get_expr_globals(self.expression)
|
|
2598
2611
|
lazy_expr = eval(self.expression, _globals, self.operands)
|
|
2599
2612
|
if not isinstance(lazy_expr, blosc2.LazyExpr):
|
|
2600
|
-
key,
|
|
2613
|
+
key, mask = process_key(item, self.shape)
|
|
2601
2614
|
# An immediate evaluation happened (e.g. all operands are numpy arrays)
|
|
2602
2615
|
if hasattr(self, "_where_args"):
|
|
2603
2616
|
# We need to apply the where() operation
|
|
@@ -2614,7 +2627,11 @@ class LazyExpr(LazyArray):
|
|
|
2614
2627
|
# This is not exactly optimized, but it works for now
|
|
2615
2628
|
self._output[:] = lazy_expr[key]
|
|
2616
2629
|
return self._output
|
|
2617
|
-
|
|
2630
|
+
arr = lazy_expr[key]
|
|
2631
|
+
if builtins.sum(mask) > 0:
|
|
2632
|
+
# Correct shape to adjust to NumPy convention
|
|
2633
|
+
arr.shape = tuple(arr.shape[i] for i in range(len(mask)) if not mask[i])
|
|
2634
|
+
return arr
|
|
2618
2635
|
|
|
2619
2636
|
return chunked_eval(lazy_expr.expression, lazy_expr.operands, item, **kwargs)
|
|
2620
2637
|
|
|
@@ -2714,6 +2731,9 @@ class LazyExpr(LazyArray):
|
|
|
2714
2731
|
kwargs = {"_getitem": True}
|
|
2715
2732
|
return self.compute(item, **kwargs)
|
|
2716
2733
|
|
|
2734
|
+
def slice(self, item):
|
|
2735
|
+
return self.compute(item) # should do a slice since _getitem = False
|
|
2736
|
+
|
|
2717
2737
|
def __str__(self):
|
|
2718
2738
|
return f"{self.expression}"
|
|
2719
2739
|
|
|
@@ -3276,14 +3296,16 @@ def _open_lazyarray(array):
|
|
|
3276
3296
|
operands = lazyarray["operands"]
|
|
3277
3297
|
parent_path = Path(array.schunk.urlpath).parent
|
|
3278
3298
|
operands_dict = {}
|
|
3299
|
+
missing_ops = {}
|
|
3279
3300
|
for key, value in operands.items():
|
|
3280
3301
|
if isinstance(value, str):
|
|
3281
3302
|
value = parent_path / value
|
|
3282
3303
|
try:
|
|
3283
3304
|
op = blosc2.open(value)
|
|
3284
3305
|
except FileNotFoundError:
|
|
3285
|
-
|
|
3286
|
-
|
|
3306
|
+
missing_ops[key] = value
|
|
3307
|
+
else:
|
|
3308
|
+
operands_dict[key] = op
|
|
3287
3309
|
elif isinstance(value, dict):
|
|
3288
3310
|
# C2Array
|
|
3289
3311
|
operands_dict[key] = blosc2.C2Array(
|
|
@@ -3294,16 +3316,17 @@ def _open_lazyarray(array):
|
|
|
3294
3316
|
raise TypeError("Error when retrieving the operands")
|
|
3295
3317
|
|
|
3296
3318
|
expr = lazyarray["expression"]
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3319
|
+
if missing_ops:
|
|
3320
|
+
exc = exceptions.MissingOperands(expr, missing_ops)
|
|
3321
|
+
exc.expr = expr
|
|
3322
|
+
exc.missing_ops = missing_ops
|
|
3323
|
+
raise exc
|
|
3324
|
+
|
|
3325
|
+
new_expr = LazyExpr._new_expr(expr, operands_dict, guess=True, out=None, where=None)
|
|
3326
|
+
# Make the array info available for the user (only available when opened from disk)
|
|
3327
|
+
new_expr.array = array
|
|
3328
|
+
# We want to expose schunk too, so that .info() can be used on the LazyArray
|
|
3329
|
+
new_expr.schunk = array.schunk
|
|
3307
3330
|
return new_expr
|
|
3308
3331
|
|
|
3309
3332
|
|
|
@@ -3523,6 +3523,71 @@ def copy(array: NDArray, dtype: np.dtype | str = None, **kwargs: Any) -> NDArray
|
|
|
3523
3523
|
return array.copy(dtype, **kwargs)
|
|
3524
3524
|
|
|
3525
3525
|
|
|
3526
|
+
def concatenate(arrays: list[NDArray], /, axis=0, **kwargs: Any) -> NDArray: # noqa: C901
|
|
3527
|
+
"""Concatenate two arrays along a specified axis.
|
|
3528
|
+
|
|
3529
|
+
Parameters
|
|
3530
|
+
----------
|
|
3531
|
+
arrays: list of :ref:`NDArray`
|
|
3532
|
+
A list containing two or more NDArray instances to be concatenated.
|
|
3533
|
+
axis: int, optional
|
|
3534
|
+
The axis along which the arrays will be concatenated. Default is 0.
|
|
3535
|
+
|
|
3536
|
+
Other Parameters
|
|
3537
|
+
----------------
|
|
3538
|
+
kwargs: dict, optional
|
|
3539
|
+
Keyword arguments that are supported by the :func:`empty` constructor.
|
|
3540
|
+
|
|
3541
|
+
Returns
|
|
3542
|
+
-------
|
|
3543
|
+
out: :ref:`NDArray`
|
|
3544
|
+
A new NDArray containing the concatenated data.
|
|
3545
|
+
|
|
3546
|
+
Examples
|
|
3547
|
+
--------
|
|
3548
|
+
>>> import blosc2
|
|
3549
|
+
>>> import numpy as np
|
|
3550
|
+
>>> arr1 = blosc2.arange(0, 5, dtype=np.int32)
|
|
3551
|
+
>>> arr2 = blosc2.arange(5, 10, dtype=np.int32)
|
|
3552
|
+
>>> result = blosc2.concatenate([arr1, arr2])
|
|
3553
|
+
>>> print(result[:])
|
|
3554
|
+
[0 1 2 3 4 5 6 7 8 9]
|
|
3555
|
+
"""
|
|
3556
|
+
if len(arrays) < 2:
|
|
3557
|
+
raise ValueError("At least two arrays are required for concatenation.")
|
|
3558
|
+
arr1 = arrays[0]
|
|
3559
|
+
if not isinstance(arr1, blosc2.NDArray):
|
|
3560
|
+
raise TypeError("All inputs must be instances of blosc2.NDArray")
|
|
3561
|
+
# Do a first pass for checking array compatibility
|
|
3562
|
+
if axis < 0:
|
|
3563
|
+
axis += arr1.ndim
|
|
3564
|
+
if axis >= arr1.ndim:
|
|
3565
|
+
raise ValueError(f"Axis {axis} is out of bounds for array of dimension {arr1.ndim}.")
|
|
3566
|
+
for arr2 in arrays[1:]:
|
|
3567
|
+
if not isinstance(arr2, blosc2.NDArray):
|
|
3568
|
+
raise TypeError("All inputs must be instances of blosc2.NDArray")
|
|
3569
|
+
if arr1.ndim != arr2.ndim:
|
|
3570
|
+
raise ValueError("Both arrays must have the same number of dimensions for concatenation.")
|
|
3571
|
+
if arr1.dtype != arr2.dtype:
|
|
3572
|
+
raise ValueError("Both arrays must have the same dtype for concatenation.")
|
|
3573
|
+
# Check that the shapes match, except for the concatenation axis
|
|
3574
|
+
if arr1.shape[:axis] != arr2.shape[:axis] or arr1.shape[axis + 1 :] != arr2.shape[axis + 1 :]:
|
|
3575
|
+
raise ValueError(
|
|
3576
|
+
f"Shapes of the arrays do not match along the concatenation axis {axis}: "
|
|
3577
|
+
f"{arr1.shape} vs {arr2.shape}"
|
|
3578
|
+
)
|
|
3579
|
+
|
|
3580
|
+
kwargs = _check_ndarray_kwargs(**kwargs)
|
|
3581
|
+
# Proceed with the actual concatenation
|
|
3582
|
+
copy = True
|
|
3583
|
+
for arr2 in arrays[1:]:
|
|
3584
|
+
arr1 = blosc2_ext.concatenate(arr1, arr2, axis, copy=copy, **kwargs)
|
|
3585
|
+
# arr1 is now the result of the concatenation, so we can now just enlarge it
|
|
3586
|
+
copy = False
|
|
3587
|
+
|
|
3588
|
+
return arr1
|
|
3589
|
+
|
|
3590
|
+
|
|
3526
3591
|
def save(array: NDArray, urlpath: str, contiguous=True, **kwargs: Any) -> None:
|
|
3527
3592
|
"""Save an array to a file.
|
|
3528
3593
|
|
|
@@ -3545,9 +3610,9 @@ def save(array: NDArray, urlpath: str, contiguous=True, **kwargs: Any) -> None:
|
|
|
3545
3610
|
>>> import blosc2
|
|
3546
3611
|
>>> import numpy as np
|
|
3547
3612
|
>>> # Create an array
|
|
3548
|
-
>>> array =
|
|
3613
|
+
>>> array = blosc2.arange(0, 100, dtype=np.int64, shape=(10, 10))
|
|
3549
3614
|
>>> # Save the array to a file
|
|
3550
|
-
>>> blosc2.save(array, "array.b2")
|
|
3615
|
+
>>> blosc2.save(array, "array.b2", mode="w")
|
|
3551
3616
|
"""
|
|
3552
3617
|
array.save(urlpath, contiguous, **kwargs)
|
|
3553
3618
|
|
|
@@ -691,3 +691,58 @@ def jit(func=None, *, out=None, **kwargs): # noqa: C901
|
|
|
691
691
|
return decorator
|
|
692
692
|
else:
|
|
693
693
|
return decorator(func)
|
|
694
|
+
|
|
695
|
+
|
|
696
|
+
class PandasUdfEngine:
|
|
697
|
+
@staticmethod
|
|
698
|
+
def _ensure_numpy_data(data):
|
|
699
|
+
if not isinstance(data, np.ndarray):
|
|
700
|
+
try:
|
|
701
|
+
data = data.values
|
|
702
|
+
except AttributeError as err:
|
|
703
|
+
raise ValueError(
|
|
704
|
+
"blosc2.jit received an object of type {data.__name__}, which is not supported. "
|
|
705
|
+
"Try casting your Series or DataFrame to a NumPy dtype."
|
|
706
|
+
) from err
|
|
707
|
+
return data
|
|
708
|
+
|
|
709
|
+
@classmethod
|
|
710
|
+
def map(cls, data, func, args, kwargs, decorator, skip_na):
|
|
711
|
+
"""
|
|
712
|
+
JIT a NumPy array element-wise. In the case of Blosc2, functions are
|
|
713
|
+
expected to be vectorized NumPy operations, so the function is called
|
|
714
|
+
with the NumPy array as the function parameter, instead of calling the
|
|
715
|
+
function once for each element.
|
|
716
|
+
"""
|
|
717
|
+
raise NotImplementedError("The Blosc2 engine does not support map. Use apply instead.")
|
|
718
|
+
|
|
719
|
+
@classmethod
|
|
720
|
+
def apply(cls, data, func, args, kwargs, decorator, axis):
|
|
721
|
+
"""
|
|
722
|
+
JIT a NumPy array by column or row. In the case of Blosc2, functions are
|
|
723
|
+
expected to be vectorized NumPy operations, so the function is called
|
|
724
|
+
with the NumPy array as the function parameter, instead of calling the
|
|
725
|
+
function once for each column or row.
|
|
726
|
+
"""
|
|
727
|
+
data = cls._ensure_numpy_data(data)
|
|
728
|
+
func = decorator(func)
|
|
729
|
+
if data.ndim == 1 or axis is None:
|
|
730
|
+
# pandas Series.apply or pipe
|
|
731
|
+
return func(data, *args, **kwargs)
|
|
732
|
+
elif axis in (0, "index"):
|
|
733
|
+
# pandas apply(axis=0) column-wise
|
|
734
|
+
result = []
|
|
735
|
+
for row_idx in range(data.shape[1]):
|
|
736
|
+
result.append(func(data[:, row_idx], *args, **kwargs))
|
|
737
|
+
return np.vstack(result).transpose()
|
|
738
|
+
elif axis in (1, "columns"):
|
|
739
|
+
# pandas apply(axis=1) row-wise
|
|
740
|
+
result = []
|
|
741
|
+
for col_idx in range(data.shape[0]):
|
|
742
|
+
result.append(func(data[col_idx, :], *args, **kwargs))
|
|
743
|
+
return np.vstack(result)
|
|
744
|
+
else:
|
|
745
|
+
raise NotImplementedError(f"Unknown axis '{axis}'. Use one of 0, 1 or None.")
|
|
746
|
+
|
|
747
|
+
|
|
748
|
+
jit.__pandas_udf__ = PandasUdfEngine
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "3.4.0"
|