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.
Files changed (262) hide show
  1. {blosc2-3.3.4 → blosc2-3.4.0}/.pre-commit-config.yaml +1 -1
  2. {blosc2-3.3.4 → blosc2-3.4.0}/ANNOUNCE.rst +2 -6
  3. {blosc2-3.3.4 → blosc2-3.4.0}/CMakeLists.txt +1 -1
  4. {blosc2-3.3.4 → blosc2-3.4.0}/PKG-INFO +1 -1
  5. {blosc2-3.3.4 → blosc2-3.4.0}/README_DEVELOPERS.md +14 -0
  6. {blosc2-3.3.4 → blosc2-3.4.0}/RELEASE_NOTES.md +14 -2
  7. {blosc2-3.3.4 → blosc2-3.4.0}/doc/python-blosc2.rst +1 -1
  8. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/ndarray.rst +1 -0
  9. blosc2-3.4.0/examples/blosc2_hdf5_compression.py +95 -0
  10. blosc2-3.4.0/examples/ndarray/lazyexpr_where_indexing.py +42 -0
  11. {blosc2-3.3.4 → blosc2-3.4.0}/pyproject.toml +1 -1
  12. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/__init__.py +1 -0
  13. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/blosc2_ext.pyx +25 -0
  14. blosc2-3.4.0/src/blosc2/exceptions.py +7 -0
  15. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/lazyexpr.py +55 -32
  16. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/ndarray.py +67 -2
  17. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/proxy.py +55 -0
  18. blosc2-3.4.0/src/blosc2/version.py +1 -0
  19. blosc2-3.4.0/tests/ndarray/test_concatenate.py +64 -0
  20. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lazyexpr.py +44 -11
  21. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lazyexpr_fields.py +50 -10
  22. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_reductions.py +14 -1
  23. blosc2-3.4.0/tests/test_pandas_udf_engine.py +120 -0
  24. blosc2-3.3.4/src/blosc2/version.py +0 -1
  25. {blosc2-3.3.4 → blosc2-3.4.0}/.gitignore +0 -0
  26. {blosc2-3.3.4 → blosc2-3.4.0}/.guix/modules/python-blosc2-package.scm +0 -0
  27. {blosc2-3.3.4 → blosc2-3.4.0}/.guix-channel +0 -0
  28. {blosc2-3.3.4 → blosc2-3.4.0}/CONTRIBUTING.rst +0 -0
  29. {blosc2-3.3.4 → blosc2-3.4.0}/LICENSE.txt +0 -0
  30. {blosc2-3.3.4 → blosc2-3.4.0}/README.rst +0 -0
  31. {blosc2-3.3.4 → blosc2-3.4.0}/RELEASING.rst +0 -0
  32. {blosc2-3.3.4 → blosc2-3.4.0}/code_of_conduct.md +0 -0
  33. {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-favicon_32x32.png +0 -0
  34. {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-favicon_64x64.png +0 -0
  35. {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-logo_128.png +0 -0
  36. {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/blosc-logo_256.png +0 -0
  37. {blosc2-3.3.4 → blosc2-3.4.0}/doc/_static/css/custom.css +0 -0
  38. {blosc2-3.3.4 → blosc2-3.4.0}/doc/conf.py +0 -0
  39. {blosc2-3.3.4 → blosc2-3.4.0}/doc/development/code-of-conduct.rst +0 -0
  40. {blosc2-3.3.4 → blosc2-3.4.0}/doc/development/contributing.rst +0 -0
  41. {blosc2-3.3.4 → blosc2-3.4.0}/doc/development/index.rst +0 -0
  42. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/index.rst +0 -0
  43. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/installation.rst +0 -0
  44. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/overview.rst +0 -0
  45. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/01.ndarray-basics.ipynb +0 -0
  46. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/02.lazyarray-expressions.ipynb +0 -0
  47. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/03.lazyarray-udf.ipynb +0 -0
  48. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/04.reductions.ipynb +0 -0
  49. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/05.persistent-reductions.ipynb +0 -0
  50. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/06.remote_proxy.ipynb +0 -0
  51. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/07.schunk-basics.ipynb +0 -0
  52. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/08.schunk-slicing_and_beyond.ipynb +0 -0
  53. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/10.ucodecs-ufilters.ipynb +0 -0
  54. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/11.prefilters.ipynb +0 -0
  55. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/12.postfilters.ipynb +0 -0
  56. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/blosc2-pipeline.png +0 -0
  57. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/blosc2-pipeline.svg +0 -0
  58. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/lazyexpr-broadcast.png +0 -0
  59. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/3D-cube-plane.png +0 -0
  60. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/3D-cube.png +0 -0
  61. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/memory-access-2D-x.png +0 -0
  62. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/reductions/memory-access-2D-y.png +0 -0
  63. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/remote_proxy.png +0 -0
  64. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/backward.png +0 -0
  65. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/backward.svg +0 -0
  66. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder.png +0 -0
  67. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder.svg +0 -0
  68. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder2.png +0 -0
  69. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/decoder2.svg +0 -0
  70. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder.png +0 -0
  71. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder.svg +0 -0
  72. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder2.png +0 -0
  73. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/encoder2.svg +0 -0
  74. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/forward.png +0 -0
  75. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials/images/ucodecs-filters/forward.svg +0 -0
  76. {blosc2-3.3.4 → blosc2-3.4.0}/doc/getting_started/tutorials.rst +0 -0
  77. {blosc2-3.3.4 → blosc2-3.4.0}/doc/index.rst +0 -0
  78. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/array_operations.rst +0 -0
  79. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__getitem__.rst +0 -0
  80. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__init__.rst +0 -0
  81. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__len__.rst +0 -0
  82. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.__setitem__.rst +0 -0
  83. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.append_data.rst +0 -0
  84. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.decompress_chunk.rst +0 -0
  85. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.delete_chunk.rst +0 -0
  86. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.fill_special.rst +0 -0
  87. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.filler.rst +0 -0
  88. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.get_chunk.rst +0 -0
  89. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.get_slice.rst +0 -0
  90. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.insert_chunk.rst +0 -0
  91. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.insert_data.rst +0 -0
  92. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.iterchunks.rst +0 -0
  93. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.iterchunks_info.rst +0 -0
  94. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.postfilter.rst +0 -0
  95. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.prefilter.rst +0 -0
  96. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.remove_postfilter.rst +0 -0
  97. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.remove_prefilter.rst +0 -0
  98. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.to_cframe.rst +0 -0
  99. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.update_chunk.rst +0 -0
  100. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/autofiles/schunk/blosc2.schunk.SChunk.update_data.rst +0 -0
  101. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/c2array.rst +0 -0
  102. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/classes.rst +0 -0
  103. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/decorators.rst +0 -0
  104. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/index.rst +0 -0
  105. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/lazy_functions.rst +0 -0
  106. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/lazyarray.rst +0 -0
  107. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/linear_algebra.rst +0 -0
  108. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/low_level.rst +0 -0
  109. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/ndfield.rst +0 -0
  110. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/proxy.rst +0 -0
  111. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/proxyndsource.rst +0 -0
  112. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/proxysource.rst +0 -0
  113. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/reduction_functions.rst +0 -0
  114. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/save_load.rst +0 -0
  115. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/schunk.rst +0 -0
  116. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/simpleproxy.rst +0 -0
  117. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/storage.rst +0 -0
  118. {blosc2-3.3.4 → blosc2-3.4.0}/doc/reference/utilities.rst +0 -0
  119. {blosc2-3.3.4 → blosc2-3.4.0}/doc/release_notes/index.md +0 -0
  120. {blosc2-3.3.4 → blosc2-3.4.0}/examples/btune.py +0 -0
  121. {blosc2-3.3.4 → blosc2-3.4.0}/examples/c2array-get-slice.py +0 -0
  122. {blosc2-3.3.4 → blosc2-3.4.0}/examples/compress2_decompress2.py +0 -0
  123. {blosc2-3.3.4 → blosc2-3.4.0}/examples/compress_decompress.py +0 -0
  124. {blosc2-3.3.4 → blosc2-3.4.0}/examples/filler.py +0 -0
  125. {blosc2-3.3.4 → blosc2-3.4.0}/examples/gil.py +0 -0
  126. {blosc2-3.3.4 → blosc2-3.4.0}/examples/mmap-rw.py +0 -0
  127. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/arange-constructor.py +0 -0
  128. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/asarray_.py +0 -0
  129. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/broadcast_expr.py +0 -0
  130. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/buffer.py +0 -0
  131. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/bytedelta_filter.py +0 -0
  132. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/c2array_expr.py +0 -0
  133. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_expr.py +0 -0
  134. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_fields.py +0 -0
  135. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_udf_numba.py +0 -0
  136. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/compute_where.py +0 -0
  137. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/copy_.py +0 -0
  138. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/empty_.py +0 -0
  139. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/eye-constructor.py +0 -0
  140. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/filter_sort_fields.py +0 -0
  141. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/formats.py +0 -0
  142. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/fromiter-constructor.py +0 -0
  143. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/general_expressions.py +0 -0
  144. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/getitem.py +0 -0
  145. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/iterchunks_info.py +0 -0
  146. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/jit-expr.py +0 -0
  147. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/jit-numpy-funcs.py +0 -0
  148. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/jit-reduc.py +0 -0
  149. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/linspace-constructor.py +0 -0
  150. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/lists-vs-bools-idx.py +0 -0
  151. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/meta.py +0 -0
  152. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/ndarray_copy.py +0 -0
  153. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/ndmean.py +0 -0
  154. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/persistency.py +0 -0
  155. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/proxy-carray.py +0 -0
  156. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/proxy-ndarray.py +0 -0
  157. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_and_enlarge.py +0 -0
  158. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_expr.py +0 -0
  159. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_expr_save.py +0 -0
  160. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/reduce_string_expr.py +0 -0
  161. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/resize_.py +0 -0
  162. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/work_with_numpy.py +0 -0
  163. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ndarray/zfp_codec.py +0 -0
  164. {blosc2-3.3.4 → blosc2-3.4.0}/examples/pack_array.py +0 -0
  165. {blosc2-3.3.4 → blosc2-3.4.0}/examples/pack_tensor.py +0 -0
  166. {blosc2-3.3.4 → blosc2-3.4.0}/examples/postfilter1.py +0 -0
  167. {blosc2-3.3.4 → blosc2-3.4.0}/examples/postfilter2.py +0 -0
  168. {blosc2-3.3.4 → blosc2-3.4.0}/examples/postfilter3.py +0 -0
  169. {blosc2-3.3.4 → blosc2-3.4.0}/examples/prefilter.py +0 -0
  170. {blosc2-3.3.4 → blosc2-3.4.0}/examples/save_tensor.py +0 -0
  171. {blosc2-3.3.4 → blosc2-3.4.0}/examples/schunk.py +0 -0
  172. {blosc2-3.3.4 → blosc2-3.4.0}/examples/schunk_roundtrip.py +0 -0
  173. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ucodecs.py +0 -0
  174. {blosc2-3.3.4 → blosc2-3.4.0}/examples/ufilters.py +0 -0
  175. {blosc2-3.3.4 → blosc2-3.4.0}/examples/vlmeta.py +0 -0
  176. {blosc2-3.3.4 → blosc2-3.4.0}/generate_version.py +0 -0
  177. {blosc2-3.3.4 → blosc2-3.4.0}/guix.scm +0 -0
  178. {blosc2-3.3.4 → blosc2-3.4.0}/images/Complete-Write-Read-B2ND.png +0 -0
  179. {blosc2-3.3.4 → blosc2-3.4.0}/images/M1-i386-vs-arm64-pack.png +0 -0
  180. {blosc2-3.3.4 → blosc2-3.4.0}/images/M1-i386-vs-arm64-unpack.png +0 -0
  181. {blosc2-3.3.4 → blosc2-3.4.0}/images/Read-Partial-Slices-B2ND.png +0 -0
  182. {blosc2-3.3.4 → blosc2-3.4.0}/images/b2nd-2level-parts.png +0 -0
  183. {blosc2-3.3.4 → blosc2-3.4.0}/images/eval-expr-full-mem-M2.png +0 -0
  184. {blosc2-3.3.4 → blosc2-3.4.0}/images/eval-expr-scarce-mem-M2.png +0 -0
  185. {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-dask-large.png +0 -0
  186. {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-dask-small.png +0 -0
  187. {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-expr-large.png +0 -0
  188. {blosc2-3.3.4 → blosc2-3.4.0}/images/lazyarray-expr.png +0 -0
  189. {blosc2-3.3.4 → blosc2-3.4.0}/images/linspace-compress.png +0 -0
  190. {blosc2-3.3.4 → blosc2-3.4.0}/images/linspace-decompress.png +0 -0
  191. {blosc2-3.3.4 → blosc2-3.4.0}/images/pack-array-cratios.png +0 -0
  192. {blosc2-3.3.4 → blosc2-3.4.0}/images/reduc-float64-amd.png +0 -0
  193. {blosc2-3.3.4 → blosc2-3.4.0}/images/reduc-float64-log-amd.png +0 -0
  194. {blosc2-3.3.4 → blosc2-3.4.0}/pytest.ini +0 -0
  195. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/c2array.py +0 -0
  196. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/core.py +0 -0
  197. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/helpers.py +0 -0
  198. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/info.py +0 -0
  199. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/schunk.py +0 -0
  200. {blosc2-3.3.4 → blosc2-3.4.0}/src/blosc2/storage.py +0 -0
  201. {blosc2-3.3.4 → blosc2-3.4.0}/tests/conftest.py +0 -0
  202. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_auto_parts.py +0 -0
  203. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_buffer.py +0 -0
  204. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_c2array_expr.py +0 -0
  205. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_c2array_reductions.py +0 -0
  206. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_c2array_udf.py +0 -0
  207. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_copy.py +0 -0
  208. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_empty.py +0 -0
  209. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_evaluate.py +0 -0
  210. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_full.py +0 -0
  211. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_get_slice_nchunks.py +0 -0
  212. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_getitem.py +0 -0
  213. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_iterchunks_info.py +0 -0
  214. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_jit.py +0 -0
  215. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lazyudf.py +0 -0
  216. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_lossy.py +0 -0
  217. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_matmul.py +0 -0
  218. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_metalayers.py +0 -0
  219. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_mode.py +0 -0
  220. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_nans.py +0 -0
  221. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_ndarray.py +0 -0
  222. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_numpy.py +0 -0
  223. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_persistency.py +0 -0
  224. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_proxy.py +0 -0
  225. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_proxy_c2array.py +0 -0
  226. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_proxy_expr.py +0 -0
  227. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_resize.py +0 -0
  228. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_setitem.py +0 -0
  229. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_slice.py +0 -0
  230. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_squeeze.py +0 -0
  231. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_struct_dtype.py +0 -0
  232. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_transpose.py +0 -0
  233. {blosc2-3.3.4 → blosc2-3.4.0}/tests/ndarray/test_zeros.py +0 -0
  234. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_bytes_array.py +0 -0
  235. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_comp_info.py +0 -0
  236. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_compress2.py +0 -0
  237. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_compression_parameters.py +0 -0
  238. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_compressors.py +0 -0
  239. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_decompress.py +0 -0
  240. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_iterchunks.py +0 -0
  241. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_mmap.py +0 -0
  242. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_open.py +0 -0
  243. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_open_c2array.py +0 -0
  244. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_pathlib.py +0 -0
  245. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_postfilters.py +0 -0
  246. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_prefilters.py +0 -0
  247. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_proxy_schunk.py +0 -0
  248. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_python_blosc.py +0 -0
  249. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk.py +0 -0
  250. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_constructor.py +0 -0
  251. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_delete.py +0 -0
  252. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_get_slice.py +0 -0
  253. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_get_slice_nchunks.py +0 -0
  254. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_insert.py +0 -0
  255. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_set_slice.py +0 -0
  256. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_schunk_update.py +0 -0
  257. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_storage.py +0 -0
  258. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_tensor.py +0 -0
  259. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_ucodecs.py +0 -0
  260. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_ufilters.py +0 -0
  261. {blosc2-3.3.4 → blosc2-3.4.0}/tests/test_vlmeta.py +0 -0
  262. {blosc2-3.3.4 → blosc2-3.4.0}/update_version.py +0 -0
@@ -16,7 +16,7 @@ repos:
16
16
  - id: trailing-whitespace
17
17
 
18
18
  - repo: https://github.com/astral-sh/ruff-pre-commit
19
- rev: v0.11.8
19
+ rev: v0.11.12
20
20
  hooks:
21
21
  - id: ruff
22
22
  args: ["--fix", "--show-fixes"]
@@ -1,11 +1,7 @@
1
- Announcing Python-Blosc2 3.3.4
1
+ Announcing Python-Blosc2 3.4.0
2
2
  ==============================
3
3
 
4
- This is a bugfix release, with some minor optimizations. We further improved the
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 4ef3c7440a85632e6c8b6c5d2a9e651e45569fc1 # v2.17.1 + mmap fix
53
+ GIT_TAG 1c2f8bb0c914c43e23b751fbcf6642cd7aec09db # v2.18.0 (concatenate added)
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.4
3
+ Version: 3.4.0
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>
@@ -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.3 released on 2025-05-14!</a>
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>
@@ -72,6 +72,7 @@ Constructors
72
72
 
73
73
  asarray
74
74
  copy
75
+ concatenate
75
76
  empty
76
77
  frombuffer
77
78
  fromiter
@@ -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])
@@ -41,7 +41,7 @@ dependencies = [
41
41
  "py-cpuinfo; platform_machine != 'wasm32'",
42
42
  "requests",
43
43
  ]
44
- version = "3.3.4"
44
+ version = "3.4.0"
45
45
 
46
46
 
47
47
  [project.optional-dependencies]
@@ -238,6 +238,7 @@ from .ndarray import (
238
238
  sort,
239
239
  reshape,
240
240
  copy,
241
+ concatenate,
241
242
  empty,
242
243
  frombuffer,
243
244
  fromiter,
@@ -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
@@ -0,0 +1,7 @@
1
+ class MissingOperands(ValueError):
2
+ def __init__(self, expr, missing_ops):
3
+ self.expr = expr
4
+ self.missing_ops = missing_ops
5
+
6
+ message = f'Lazy expression "{expr}" with missing operands: {missing_ops}'
7
+ super().__init__(message)
@@ -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 not None, only the chunks that intersect with the slices
281
- in items will be evaluated.
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
- The slice(s) to be retrieved. Note that step parameter is not yet honored.
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
- if _slice is not None and _slice != ():
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 orig_slice is not None:
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 retrieved. Note that step parameter is not honored yet.
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, _ = process_key(item, self.shape)
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
- return lazy_expr[key]
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
- op = None
3286
- operands_dict[key] = op
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
- try:
3298
- new_expr = LazyExpr._new_expr(expr, operands_dict, guess=True, out=None, where=None)
3299
- # Make the array info available for the user (only available when opened from disk)
3300
- new_expr.array = array
3301
- # We want to expose schunk too, so that .info() can be used on the LazyArray
3302
- new_expr.schunk = array.schunk
3303
- except RuntimeError:
3304
- # Something unexpected happened. Avoid guessing and return something that
3305
- # can be introspected.
3306
- new_expr = LazyExpr._new_expr(expr, operands_dict, guess=False, out=None, where=None)
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 = np.arange(0, 100, dtype=np.int64).reshape(10, 10)
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"