numcodecs 0.13.1__cp313-cp313-macosx_10_13_x86_64.whl
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.
Potentially problematic release.
This version of numcodecs might be problematic. Click here for more details.
- numcodecs/__init__.py +143 -0
- numcodecs/_shuffle.cpython-313-darwin.so +0 -0
- numcodecs/abc.py +126 -0
- numcodecs/astype.py +76 -0
- numcodecs/base64.py +27 -0
- numcodecs/bitround.py +79 -0
- numcodecs/blosc.cpython-313-darwin.so +0 -0
- numcodecs/bz2.py +45 -0
- numcodecs/categorize.py +101 -0
- numcodecs/checksum32.py +94 -0
- numcodecs/compat.py +208 -0
- numcodecs/compat_ext.cpython-313-darwin.so +0 -0
- numcodecs/delta.py +97 -0
- numcodecs/fixedscaleoffset.py +132 -0
- numcodecs/fletcher32.cpython-313-darwin.so +0 -0
- numcodecs/gzip.py +52 -0
- numcodecs/jenkins.cpython-313-darwin.so +0 -0
- numcodecs/json.py +107 -0
- numcodecs/lz4.cpython-313-darwin.so +0 -0
- numcodecs/lzma.py +69 -0
- numcodecs/msgpacks.py +86 -0
- numcodecs/ndarray_like.py +65 -0
- numcodecs/packbits.py +85 -0
- numcodecs/pcodec.py +89 -0
- numcodecs/pickles.py +55 -0
- numcodecs/quantize.py +100 -0
- numcodecs/registry.py +72 -0
- numcodecs/shuffle.py +61 -0
- numcodecs/tests/__init__.py +3 -0
- numcodecs/tests/common.py +354 -0
- numcodecs/tests/package_with_entrypoint/__init__.py +11 -0
- numcodecs/tests/package_with_entrypoint-0.1.dist-info/entry_points.txt +2 -0
- numcodecs/tests/test_astype.py +74 -0
- numcodecs/tests/test_base64.py +81 -0
- numcodecs/tests/test_bitround.py +81 -0
- numcodecs/tests/test_blosc.py +277 -0
- numcodecs/tests/test_bz2.py +66 -0
- numcodecs/tests/test_categorize.py +87 -0
- numcodecs/tests/test_checksum32.py +58 -0
- numcodecs/tests/test_compat.py +108 -0
- numcodecs/tests/test_delta.py +60 -0
- numcodecs/tests/test_entrypoints.py +24 -0
- numcodecs/tests/test_entrypoints_backport.py +35 -0
- numcodecs/tests/test_fixedscaleoffset.py +69 -0
- numcodecs/tests/test_fletcher32.py +56 -0
- numcodecs/tests/test_gzip.py +110 -0
- numcodecs/tests/test_jenkins.py +150 -0
- numcodecs/tests/test_json.py +85 -0
- numcodecs/tests/test_lz4.py +83 -0
- numcodecs/tests/test_lzma.py +90 -0
- numcodecs/tests/test_msgpacks.py +123 -0
- numcodecs/tests/test_ndarray_like.py +48 -0
- numcodecs/tests/test_packbits.py +39 -0
- numcodecs/tests/test_pcodec.py +80 -0
- numcodecs/tests/test_pickles.py +61 -0
- numcodecs/tests/test_quantize.py +76 -0
- numcodecs/tests/test_registry.py +40 -0
- numcodecs/tests/test_shuffle.py +168 -0
- numcodecs/tests/test_vlen_array.py +97 -0
- numcodecs/tests/test_vlen_bytes.py +93 -0
- numcodecs/tests/test_vlen_utf8.py +91 -0
- numcodecs/tests/test_zfpy.py +98 -0
- numcodecs/tests/test_zlib.py +94 -0
- numcodecs/tests/test_zstd.py +92 -0
- numcodecs/version.py +16 -0
- numcodecs/vlen.cpython-313-darwin.so +0 -0
- numcodecs/zfpy.py +111 -0
- numcodecs/zlib.py +42 -0
- numcodecs/zstd.cpython-313-darwin.so +0 -0
- numcodecs-0.13.1.dist-info/LICENSE.txt +21 -0
- numcodecs-0.13.1.dist-info/METADATA +64 -0
- numcodecs-0.13.1.dist-info/RECORD +74 -0
- numcodecs-0.13.1.dist-info/WHEEL +5 -0
- numcodecs-0.13.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,354 @@
|
|
|
1
|
+
import array
|
|
2
|
+
import json as _json
|
|
3
|
+
import os
|
|
4
|
+
from glob import glob
|
|
5
|
+
|
|
6
|
+
import numpy as np
|
|
7
|
+
import pytest
|
|
8
|
+
from numpy.testing import assert_array_almost_equal, assert_array_equal
|
|
9
|
+
|
|
10
|
+
# star import needed for repr tests so eval finds names
|
|
11
|
+
from numcodecs import * # noqa: F403
|
|
12
|
+
from numcodecs.compat import ensure_bytes, ensure_ndarray
|
|
13
|
+
from numcodecs.registry import get_codec
|
|
14
|
+
|
|
15
|
+
greetings = [
|
|
16
|
+
'¡Hola mundo!',
|
|
17
|
+
'Hej Världen!',
|
|
18
|
+
'Servus Woid!',
|
|
19
|
+
'Hei maailma!',
|
|
20
|
+
'Xin chào thế giới',
|
|
21
|
+
'Njatjeta Botë!',
|
|
22
|
+
'Γεια σου κόσμε!',
|
|
23
|
+
'こんにちは世界',
|
|
24
|
+
'世界,你好!',
|
|
25
|
+
'Helló, világ!',
|
|
26
|
+
'Zdravo svete!',
|
|
27
|
+
'เฮลโลเวิลด์',
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def compare_arrays(arr, res, precision=None):
|
|
32
|
+
# ensure numpy array with matching dtype
|
|
33
|
+
res = ensure_ndarray(res).view(arr.dtype)
|
|
34
|
+
|
|
35
|
+
# convert to correct shape
|
|
36
|
+
if arr.flags.f_contiguous:
|
|
37
|
+
order = 'F'
|
|
38
|
+
else:
|
|
39
|
+
order = 'C'
|
|
40
|
+
res = res.reshape(arr.shape, order=order)
|
|
41
|
+
|
|
42
|
+
# exact compare
|
|
43
|
+
if precision is None:
|
|
44
|
+
assert_array_equal(arr, res)
|
|
45
|
+
|
|
46
|
+
# fuzzy compare
|
|
47
|
+
else:
|
|
48
|
+
assert_array_almost_equal(arr, res, decimal=precision)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def check_encode_decode(arr, codec, precision=None):
|
|
52
|
+
# N.B., watch out here with blosc compressor, if the itemsize of
|
|
53
|
+
# the source buffer is different then the results of encoding
|
|
54
|
+
# (i.e., compression) may be different. Hence we *do not* require that
|
|
55
|
+
# the results of encoding be identical for all possible inputs, rather
|
|
56
|
+
# we just require that the results of the encode/decode round-trip can
|
|
57
|
+
# be compared to the original array.
|
|
58
|
+
|
|
59
|
+
# encoding should support any object exporting the buffer protocol
|
|
60
|
+
|
|
61
|
+
# test encoding of numpy array
|
|
62
|
+
enc = codec.encode(arr)
|
|
63
|
+
dec = codec.decode(enc)
|
|
64
|
+
compare_arrays(arr, dec, precision=precision)
|
|
65
|
+
|
|
66
|
+
# test encoding of bytes
|
|
67
|
+
buf = arr.tobytes(order='A')
|
|
68
|
+
enc = codec.encode(buf)
|
|
69
|
+
dec = codec.decode(enc)
|
|
70
|
+
compare_arrays(arr, dec, precision=precision)
|
|
71
|
+
|
|
72
|
+
# test encoding of bytearray
|
|
73
|
+
buf = bytearray(arr.tobytes(order='A'))
|
|
74
|
+
enc = codec.encode(buf)
|
|
75
|
+
dec = codec.decode(enc)
|
|
76
|
+
compare_arrays(arr, dec, precision=precision)
|
|
77
|
+
|
|
78
|
+
# test encoding of array.array
|
|
79
|
+
buf = array.array('b', arr.tobytes(order='A'))
|
|
80
|
+
enc = codec.encode(buf)
|
|
81
|
+
dec = codec.decode(enc)
|
|
82
|
+
compare_arrays(arr, dec, precision=precision)
|
|
83
|
+
|
|
84
|
+
# decoding should support any object exporting the buffer protocol,
|
|
85
|
+
|
|
86
|
+
# setup
|
|
87
|
+
enc_bytes = ensure_bytes(enc)
|
|
88
|
+
|
|
89
|
+
# test decoding of raw bytes
|
|
90
|
+
dec = codec.decode(enc_bytes)
|
|
91
|
+
compare_arrays(arr, dec, precision=precision)
|
|
92
|
+
|
|
93
|
+
# test decoding of bytearray
|
|
94
|
+
dec = codec.decode(bytearray(enc_bytes))
|
|
95
|
+
compare_arrays(arr, dec, precision=precision)
|
|
96
|
+
|
|
97
|
+
# test decoding of array.array
|
|
98
|
+
buf = array.array('b', enc_bytes)
|
|
99
|
+
dec = codec.decode(buf)
|
|
100
|
+
compare_arrays(arr, dec, precision=precision)
|
|
101
|
+
|
|
102
|
+
# test decoding of numpy array
|
|
103
|
+
buf = np.frombuffer(enc_bytes, dtype='u1')
|
|
104
|
+
dec = codec.decode(buf)
|
|
105
|
+
compare_arrays(arr, dec, precision=precision)
|
|
106
|
+
|
|
107
|
+
# test decoding directly into numpy array
|
|
108
|
+
out = np.empty_like(arr)
|
|
109
|
+
codec.decode(enc_bytes, out=out)
|
|
110
|
+
compare_arrays(arr, out, precision=precision)
|
|
111
|
+
|
|
112
|
+
# test decoding directly into bytearray
|
|
113
|
+
out = bytearray(arr.nbytes)
|
|
114
|
+
codec.decode(enc_bytes, out=out)
|
|
115
|
+
# noinspection PyTypeChecker
|
|
116
|
+
compare_arrays(arr, out, precision=precision)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def check_encode_decode_partial(arr, codec, precision=None):
|
|
120
|
+
# N.B., watch out here with blosc compressor, if the itemsize of
|
|
121
|
+
# the source buffer is different then the results of encoding
|
|
122
|
+
# (i.e., compression) may be different. Hence we *do not* require that
|
|
123
|
+
# the results of encoding be identical for all possible inputs, rather
|
|
124
|
+
# we just require that the results of the encode/decode round-trip can
|
|
125
|
+
# be compared to the original array.
|
|
126
|
+
|
|
127
|
+
itemsize = arr.itemsize
|
|
128
|
+
start, nitems = 5, 10
|
|
129
|
+
compare_arr = arr[start : start + nitems]
|
|
130
|
+
# test encoding of numpy array
|
|
131
|
+
enc = codec.encode(arr)
|
|
132
|
+
dec = codec.decode_partial(enc, start, nitems)
|
|
133
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
134
|
+
|
|
135
|
+
# out = np.empty_like(compare_arr)
|
|
136
|
+
out = np.empty_like(compare_arr)
|
|
137
|
+
print(len(out))
|
|
138
|
+
|
|
139
|
+
# test partial decode of encoded bytes
|
|
140
|
+
buf = arr.tobytes(order='A')
|
|
141
|
+
enc = codec.encode(buf)
|
|
142
|
+
dec = codec.decode_partial(enc, start * itemsize, nitems * itemsize, out=out)
|
|
143
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
144
|
+
|
|
145
|
+
# test partial decode of encoded bytearray
|
|
146
|
+
buf = bytearray(arr.tobytes(order='A'))
|
|
147
|
+
enc = codec.encode(buf)
|
|
148
|
+
dec = codec.decode_partial(enc, start * itemsize, nitems * itemsize, out=out)
|
|
149
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
150
|
+
|
|
151
|
+
# test partial decode of encoded array.array
|
|
152
|
+
buf = array.array('b', arr.tobytes(order='A'))
|
|
153
|
+
enc = codec.encode(buf)
|
|
154
|
+
dec = codec.decode_partial(enc, start * itemsize, nitems * itemsize, out=out)
|
|
155
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
156
|
+
|
|
157
|
+
# # decoding should support any object exporting the buffer protocol,
|
|
158
|
+
|
|
159
|
+
# # setup
|
|
160
|
+
enc_bytes = ensure_bytes(enc)
|
|
161
|
+
|
|
162
|
+
# test decoding of raw bytes into numpy array
|
|
163
|
+
dec = codec.decode_partial(enc_bytes, start * itemsize, nitems * itemsize, out=out)
|
|
164
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
165
|
+
|
|
166
|
+
# test partial decoding of bytearray
|
|
167
|
+
dec = codec.decode_partial(bytearray(enc_bytes), start * itemsize, nitems * itemsize, out=out)
|
|
168
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
169
|
+
|
|
170
|
+
# test partial decoding of array.array
|
|
171
|
+
buf = array.array('b', enc_bytes)
|
|
172
|
+
dec = codec.decode_partial(buf, start * itemsize, nitems * itemsize, out=out)
|
|
173
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
174
|
+
|
|
175
|
+
# test decoding of numpy array into numpy array
|
|
176
|
+
buf = np.frombuffer(enc_bytes, dtype='u1')
|
|
177
|
+
dec = codec.decode_partial(buf, start * itemsize, nitems * itemsize, out=out)
|
|
178
|
+
compare_arrays(compare_arr, dec, precision=precision)
|
|
179
|
+
|
|
180
|
+
# test decoding directly into bytearray
|
|
181
|
+
out = bytearray(compare_arr.nbytes)
|
|
182
|
+
codec.decode_partial(enc_bytes, start * itemsize, nitems * itemsize, out=out)
|
|
183
|
+
# noinspection PyTypeChecker
|
|
184
|
+
compare_arrays(compare_arr, out, precision=precision)
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def assert_array_items_equal(res, arr):
|
|
188
|
+
assert isinstance(res, np.ndarray)
|
|
189
|
+
res = res.reshape(-1, order='A')
|
|
190
|
+
arr = arr.reshape(-1, order='A')
|
|
191
|
+
assert res.shape == arr.shape
|
|
192
|
+
assert res.dtype == arr.dtype
|
|
193
|
+
|
|
194
|
+
# numpy asserts don't compare object arrays
|
|
195
|
+
# properly; assert that we have the same nans
|
|
196
|
+
# and values
|
|
197
|
+
arr = arr.ravel().tolist()
|
|
198
|
+
res = res.ravel().tolist()
|
|
199
|
+
for a, r in zip(arr, res, strict=True):
|
|
200
|
+
if isinstance(a, np.ndarray):
|
|
201
|
+
assert_array_equal(a, r)
|
|
202
|
+
elif a != a:
|
|
203
|
+
assert r != r
|
|
204
|
+
else:
|
|
205
|
+
assert a == r
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def check_encode_decode_array(arr, codec):
|
|
209
|
+
enc = codec.encode(arr)
|
|
210
|
+
dec = codec.decode(enc)
|
|
211
|
+
assert_array_items_equal(arr, dec)
|
|
212
|
+
|
|
213
|
+
out = np.empty_like(arr)
|
|
214
|
+
codec.decode(enc, out=out)
|
|
215
|
+
assert_array_items_equal(arr, out)
|
|
216
|
+
|
|
217
|
+
enc = codec.encode(arr)
|
|
218
|
+
dec = codec.decode(ensure_ndarray(enc))
|
|
219
|
+
assert_array_items_equal(arr, dec)
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def check_encode_decode_array_to_bytes(arr, codec):
|
|
223
|
+
enc = codec.encode(arr)
|
|
224
|
+
dec = codec.decode(enc)
|
|
225
|
+
assert_array_items_equal(arr, dec)
|
|
226
|
+
|
|
227
|
+
out = np.empty_like(arr)
|
|
228
|
+
codec.decode(enc, out=out)
|
|
229
|
+
assert_array_items_equal(arr, out)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
def check_config(codec):
|
|
233
|
+
config = codec.get_config()
|
|
234
|
+
# round-trip through JSON to check serialization
|
|
235
|
+
config = _json.loads(_json.dumps(config))
|
|
236
|
+
assert codec == get_codec(config)
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def check_repr(stmt):
|
|
240
|
+
# check repr matches instantiation statement
|
|
241
|
+
codec = eval(stmt)
|
|
242
|
+
actual = repr(codec)
|
|
243
|
+
assert stmt == actual
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def check_backwards_compatibility(codec_id, arrays, codecs, precision=None, prefix=None):
|
|
247
|
+
# setup directory to hold data fixture
|
|
248
|
+
if prefix:
|
|
249
|
+
fixture_dir = os.path.join('fixture', codec_id, prefix)
|
|
250
|
+
else:
|
|
251
|
+
fixture_dir = os.path.join('fixture', codec_id)
|
|
252
|
+
if not os.path.exists(fixture_dir): # pragma: no cover
|
|
253
|
+
os.makedirs(fixture_dir)
|
|
254
|
+
|
|
255
|
+
# save fixture data
|
|
256
|
+
for i, arr in enumerate(arrays):
|
|
257
|
+
arr_fn = os.path.join(fixture_dir, f'array.{i:02d}.npy')
|
|
258
|
+
if not os.path.exists(arr_fn): # pragma: no cover
|
|
259
|
+
np.save(arr_fn, arr)
|
|
260
|
+
|
|
261
|
+
# load fixture data
|
|
262
|
+
for arr_fn in glob(os.path.join(fixture_dir, 'array.*.npy')):
|
|
263
|
+
# setup
|
|
264
|
+
i = int(arr_fn.split('.')[-2])
|
|
265
|
+
arr = np.load(arr_fn, allow_pickle=True)
|
|
266
|
+
arr_bytes = arr.tobytes(order='A')
|
|
267
|
+
if arr.flags.f_contiguous:
|
|
268
|
+
order = 'F'
|
|
269
|
+
else:
|
|
270
|
+
order = 'C'
|
|
271
|
+
|
|
272
|
+
for j, codec in enumerate(codecs):
|
|
273
|
+
if codec is None:
|
|
274
|
+
pytest.skip("codec has been removed")
|
|
275
|
+
|
|
276
|
+
# setup a directory to hold encoded data
|
|
277
|
+
codec_dir = os.path.join(fixture_dir, f'codec.{j:02d}')
|
|
278
|
+
if not os.path.exists(codec_dir): # pragma: no cover
|
|
279
|
+
os.makedirs(codec_dir)
|
|
280
|
+
|
|
281
|
+
# file with codec configuration information
|
|
282
|
+
codec_fn = os.path.join(codec_dir, 'config.json')
|
|
283
|
+
# one time save config
|
|
284
|
+
if not os.path.exists(codec_fn): # pragma: no cover
|
|
285
|
+
with open(codec_fn, mode='w') as cf:
|
|
286
|
+
_json.dump(codec.get_config(), cf, sort_keys=True, indent=4)
|
|
287
|
+
# load config and compare with expectation
|
|
288
|
+
with open(codec_fn) as cf:
|
|
289
|
+
config = _json.load(cf)
|
|
290
|
+
assert codec == get_codec(config)
|
|
291
|
+
|
|
292
|
+
enc_fn = os.path.join(codec_dir, f'encoded.{i:02d}.dat')
|
|
293
|
+
|
|
294
|
+
# one time encode and save array
|
|
295
|
+
if not os.path.exists(enc_fn): # pragma: no cover
|
|
296
|
+
enc = codec.encode(arr)
|
|
297
|
+
enc = ensure_bytes(enc)
|
|
298
|
+
with open(enc_fn, mode='wb') as ef:
|
|
299
|
+
ef.write(enc)
|
|
300
|
+
|
|
301
|
+
# load and decode data
|
|
302
|
+
with open(enc_fn, mode='rb') as ef:
|
|
303
|
+
enc = ef.read()
|
|
304
|
+
dec = codec.decode(enc)
|
|
305
|
+
dec_arr = ensure_ndarray(dec).reshape(-1, order='A')
|
|
306
|
+
dec_arr = dec_arr.view(dtype=arr.dtype).reshape(arr.shape, order=order)
|
|
307
|
+
if precision and precision[j] is not None:
|
|
308
|
+
assert_array_almost_equal(arr, dec_arr, decimal=precision[j])
|
|
309
|
+
elif arr.dtype == 'object':
|
|
310
|
+
assert_array_items_equal(arr, dec_arr)
|
|
311
|
+
else:
|
|
312
|
+
assert_array_equal(arr, dec_arr)
|
|
313
|
+
assert arr_bytes == ensure_bytes(dec)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def check_err_decode_object_buffer(compressor):
|
|
317
|
+
# cannot decode directly into object array, leads to segfaults
|
|
318
|
+
a = np.arange(10)
|
|
319
|
+
enc = compressor.encode(a)
|
|
320
|
+
out = np.empty(10, dtype=object)
|
|
321
|
+
with pytest.raises(TypeError):
|
|
322
|
+
compressor.decode(enc, out=out)
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def check_err_encode_object_buffer(compressor):
|
|
326
|
+
# compressors cannot encode object array
|
|
327
|
+
a = np.array(['foo', 'bar', 'baz'], dtype=object)
|
|
328
|
+
with pytest.raises(TypeError):
|
|
329
|
+
compressor.encode(a)
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def check_max_buffer_size(codec):
|
|
333
|
+
for max_buffer_size in (4, 64, 1024):
|
|
334
|
+
old_max_buffer_size = codec.max_buffer_size
|
|
335
|
+
try:
|
|
336
|
+
codec.max_buffer_size = max_buffer_size
|
|
337
|
+
# Just up the max_buffer_size is fine.
|
|
338
|
+
codec.encode(np.zeros(max_buffer_size - 1, dtype=np.int8))
|
|
339
|
+
codec.encode(np.zeros(max_buffer_size, dtype=np.int8))
|
|
340
|
+
|
|
341
|
+
buffers = [
|
|
342
|
+
bytes(b"x" * (max_buffer_size + 1)),
|
|
343
|
+
np.zeros(max_buffer_size + 1, dtype=np.int8),
|
|
344
|
+
np.zeros(max_buffer_size + 2, dtype=np.int8),
|
|
345
|
+
np.zeros(max_buffer_size, dtype=np.int16),
|
|
346
|
+
np.zeros(max_buffer_size, dtype=np.int32),
|
|
347
|
+
]
|
|
348
|
+
for buf in buffers:
|
|
349
|
+
with pytest.raises(ValueError):
|
|
350
|
+
codec.encode(buf)
|
|
351
|
+
with pytest.raises(ValueError):
|
|
352
|
+
codec.decode(buf)
|
|
353
|
+
finally:
|
|
354
|
+
codec.max_buffer_size = old_max_buffer_size
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from numpy.testing import assert_array_equal
|
|
3
|
+
|
|
4
|
+
from numcodecs.astype import AsType
|
|
5
|
+
from numcodecs.tests.common import (
|
|
6
|
+
check_backwards_compatibility,
|
|
7
|
+
check_config,
|
|
8
|
+
check_encode_decode,
|
|
9
|
+
check_repr,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
# mix of dtypes: integer, float
|
|
13
|
+
# mix of shapes: 1D, 2D, 3D
|
|
14
|
+
# mix of orders: C, F
|
|
15
|
+
arrays = [
|
|
16
|
+
np.arange(1000, dtype='i4'),
|
|
17
|
+
np.linspace(1000, 1001, 1000, dtype='f8').reshape(100, 10),
|
|
18
|
+
np.random.normal(loc=1000, scale=1, size=(10, 10, 10)),
|
|
19
|
+
np.random.randint(0, 200, size=1000, dtype='u2').reshape(100, 10, order='F'),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def test_encode_decode():
|
|
24
|
+
for arr in arrays:
|
|
25
|
+
codec = AsType(encode_dtype=arr.dtype, decode_dtype=arr.dtype)
|
|
26
|
+
check_encode_decode(arr, codec)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_decode():
|
|
30
|
+
encode_dtype, decode_dtype = '<i4', '<i8'
|
|
31
|
+
codec = AsType(encode_dtype=encode_dtype, decode_dtype=decode_dtype)
|
|
32
|
+
arr = np.arange(10, 20, 1, dtype=encode_dtype)
|
|
33
|
+
expect = arr.astype(decode_dtype)
|
|
34
|
+
actual = codec.decode(arr)
|
|
35
|
+
assert_array_equal(expect, actual)
|
|
36
|
+
assert np.dtype(decode_dtype) == actual.dtype
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_encode():
|
|
40
|
+
encode_dtype, decode_dtype = '<i4', '<i8'
|
|
41
|
+
codec = AsType(encode_dtype=encode_dtype, decode_dtype=decode_dtype)
|
|
42
|
+
arr = np.arange(10, 20, 1, dtype=decode_dtype)
|
|
43
|
+
expect = arr.astype(encode_dtype)
|
|
44
|
+
actual = codec.encode(arr)
|
|
45
|
+
assert_array_equal(expect, actual)
|
|
46
|
+
assert np.dtype(encode_dtype) == actual.dtype
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_config():
|
|
50
|
+
encode_dtype, decode_dtype = '<i4', '<i8'
|
|
51
|
+
codec = AsType(encode_dtype=encode_dtype, decode_dtype=decode_dtype)
|
|
52
|
+
check_config(codec)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_repr():
|
|
56
|
+
check_repr("AsType(encode_dtype='<i4', decode_dtype='<i2')")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_backwards_compatibility():
|
|
60
|
+
# integers
|
|
61
|
+
arrs = [
|
|
62
|
+
np.arange(1000, dtype='<i4'),
|
|
63
|
+
np.random.randint(0, 200, size=1000, dtype='i4').astype('<i4').reshape(100, 10, order='F'),
|
|
64
|
+
]
|
|
65
|
+
codec = AsType(encode_dtype='<i2', decode_dtype='<i4')
|
|
66
|
+
check_backwards_compatibility(AsType.codec_id, arrs, [codec], prefix='i')
|
|
67
|
+
|
|
68
|
+
# floats
|
|
69
|
+
arrs = [
|
|
70
|
+
np.linspace(1000, 1001, 1000, dtype='<f8').reshape(100, 10, order='F'),
|
|
71
|
+
np.random.normal(loc=1000, scale=1, size=(10, 10, 10)).astype('<f8'),
|
|
72
|
+
]
|
|
73
|
+
codec = AsType(encode_dtype='<f4', decode_dtype='<f8')
|
|
74
|
+
check_backwards_compatibility(AsType.codec_id, arrs, [codec], precision=[3], prefix='f')
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import itertools
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from numcodecs.base64 import Base64
|
|
7
|
+
from numcodecs.tests.common import (
|
|
8
|
+
check_backwards_compatibility,
|
|
9
|
+
check_encode_decode,
|
|
10
|
+
check_err_decode_object_buffer,
|
|
11
|
+
check_err_encode_object_buffer,
|
|
12
|
+
check_repr,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
codecs = [
|
|
16
|
+
Base64(),
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# mix of dtypes: integer, float, bool, string
|
|
21
|
+
# mix of shapes: 1D, 2D, 3D
|
|
22
|
+
# mix of orders: C, F
|
|
23
|
+
arrays = [
|
|
24
|
+
np.arange(1000, dtype="i4"),
|
|
25
|
+
np.linspace(1000, 1001, 1000, dtype="f8"),
|
|
26
|
+
np.random.normal(loc=1000, scale=1, size=(100, 10)),
|
|
27
|
+
np.random.randint(0, 2, size=1000, dtype=bool).reshape(100, 10, order="F"),
|
|
28
|
+
np.random.choice([b"a", b"bb", b"ccc"], size=1000).reshape(10, 10, 10),
|
|
29
|
+
np.random.randint(0, 2**60, size=1000, dtype="u8").view("M8[ns]"),
|
|
30
|
+
np.random.randint(0, 2**60, size=1000, dtype="u8").view("m8[ns]"),
|
|
31
|
+
np.random.randint(0, 2**25, size=1000, dtype="u8").view("M8[m]"),
|
|
32
|
+
np.random.randint(0, 2**25, size=1000, dtype="u8").view("m8[m]"),
|
|
33
|
+
np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("M8[ns]"),
|
|
34
|
+
np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("m8[ns]"),
|
|
35
|
+
np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("M8[m]"),
|
|
36
|
+
np.random.randint(-(2**63), -(2**63) + 20, size=1000, dtype="i8").view("m8[m]"),
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_encode_decode():
|
|
41
|
+
for arr, codec in itertools.product(arrays, codecs):
|
|
42
|
+
check_encode_decode(arr, codec)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def test_repr():
|
|
46
|
+
check_repr("Base64()")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_eq():
|
|
50
|
+
assert Base64() == Base64()
|
|
51
|
+
assert not Base64() != Base64()
|
|
52
|
+
assert Base64() != "foo"
|
|
53
|
+
assert "foo" != Base64()
|
|
54
|
+
assert not Base64() == "foo"
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_backwards_compatibility():
|
|
58
|
+
check_backwards_compatibility(Base64.codec_id, arrays, codecs)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_err_decode_object_buffer():
|
|
62
|
+
check_err_decode_object_buffer(Base64())
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def test_err_encode_object_buffer():
|
|
66
|
+
check_err_encode_object_buffer(Base64())
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def test_err_encode_list():
|
|
70
|
+
data = ["foo", "bar", "baz"]
|
|
71
|
+
for codec in codecs:
|
|
72
|
+
with pytest.raises(TypeError):
|
|
73
|
+
codec.encode(data)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def test_err_encode_non_contiguous():
|
|
77
|
+
# non-contiguous memory
|
|
78
|
+
arr = np.arange(1000, dtype="i4")[::2]
|
|
79
|
+
for codec in codecs:
|
|
80
|
+
with pytest.raises(ValueError):
|
|
81
|
+
codec.encode(arr)
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
from numcodecs.bitround import BitRound, max_bits
|
|
5
|
+
|
|
6
|
+
# adapted from https://github.com/milankl/BitInformation.jl/blob/main/test/round_nearest.jl
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# TODO: add other dtypes
|
|
10
|
+
@pytest.fixture(params=["float32", "float64"])
|
|
11
|
+
def dtype(request):
|
|
12
|
+
return request.param
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def round(data, keepbits):
|
|
16
|
+
codec = BitRound(keepbits=keepbits)
|
|
17
|
+
data = data.copy() # otherwise overwrites the input
|
|
18
|
+
encoded = codec.encode(data)
|
|
19
|
+
return codec.decode(encoded)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_round_zero_to_zero(dtype):
|
|
23
|
+
a = np.zeros((3, 2), dtype=dtype)
|
|
24
|
+
# Don't understand Milan's original test:
|
|
25
|
+
# How is it possible to have negative keepbits?
|
|
26
|
+
# for k in range(-5, 50):
|
|
27
|
+
for k in range(0, max_bits[dtype]):
|
|
28
|
+
ar = round(a, k)
|
|
29
|
+
np.testing.assert_equal(a, ar)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_round_one_to_one(dtype):
|
|
33
|
+
a = np.ones((3, 2), dtype=dtype)
|
|
34
|
+
for k in range(0, max_bits[dtype]):
|
|
35
|
+
ar = round(a, k)
|
|
36
|
+
np.testing.assert_equal(a, ar)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_round_minus_one_to_minus_one(dtype):
|
|
40
|
+
a = -np.ones((3, 2), dtype=dtype)
|
|
41
|
+
for k in range(0, max_bits[dtype]):
|
|
42
|
+
ar = round(a, k)
|
|
43
|
+
np.testing.assert_equal(a, ar)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def test_no_rounding(dtype):
|
|
47
|
+
a = np.random.random_sample((300, 200)).astype(dtype)
|
|
48
|
+
keepbits = max_bits[dtype]
|
|
49
|
+
ar = round(a, keepbits)
|
|
50
|
+
np.testing.assert_equal(a, ar)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
APPROX_KEEPBITS = {"float32": 11, "float64": 18}
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def test_approx_equal(dtype):
|
|
57
|
+
a = np.random.random_sample((300, 200)).astype(dtype)
|
|
58
|
+
ar = round(a, APPROX_KEEPBITS[dtype])
|
|
59
|
+
# Mimic julia behavior - https://docs.julialang.org/en/v1/base/math/#Base.isapprox
|
|
60
|
+
rtol = np.sqrt(np.finfo(np.float32).eps)
|
|
61
|
+
# This gets us much closer but still failing for ~6% of the array
|
|
62
|
+
# It does pass if we add 1 to keepbits (11 instead of 10)
|
|
63
|
+
# Is there an off-by-one issue here?
|
|
64
|
+
np.testing.assert_allclose(a, ar, rtol=rtol)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def test_idempotence(dtype):
|
|
68
|
+
a = np.random.random_sample((300, 200)).astype(dtype)
|
|
69
|
+
for k in range(20):
|
|
70
|
+
ar = round(a, k)
|
|
71
|
+
ar2 = round(a, k)
|
|
72
|
+
np.testing.assert_equal(ar, ar2)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_errors():
|
|
76
|
+
with pytest.raises(ValueError):
|
|
77
|
+
BitRound(keepbits=99).encode(np.array([0], dtype="float32"))
|
|
78
|
+
with pytest.raises(TypeError):
|
|
79
|
+
BitRound(keepbits=10).encode(np.array([0]))
|
|
80
|
+
with pytest.raises(ValueError):
|
|
81
|
+
BitRound(-1)
|