test_packbits.py 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. import numpy as np
  2. from numpy.testing import assert_array_equal, assert_equal, assert_raises
  3. import pytest
  4. from itertools import chain
  5. def test_packbits():
  6. # Copied from the docstring.
  7. a = [[[1, 0, 1], [0, 1, 0]],
  8. [[1, 1, 0], [0, 0, 1]]]
  9. for dt in '?bBhHiIlLqQ':
  10. arr = np.array(a, dtype=dt)
  11. b = np.packbits(arr, axis=-1)
  12. assert_equal(b.dtype, np.uint8)
  13. assert_array_equal(b, np.array([[[160], [64]], [[192], [32]]]))
  14. assert_raises(TypeError, np.packbits, np.array(a, dtype=float))
  15. def test_packbits_empty():
  16. shapes = [
  17. (0,), (10, 20, 0), (10, 0, 20), (0, 10, 20), (20, 0, 0), (0, 20, 0),
  18. (0, 0, 20), (0, 0, 0),
  19. ]
  20. for dt in '?bBhHiIlLqQ':
  21. for shape in shapes:
  22. a = np.empty(shape, dtype=dt)
  23. b = np.packbits(a)
  24. assert_equal(b.dtype, np.uint8)
  25. assert_equal(b.shape, (0,))
  26. def test_packbits_empty_with_axis():
  27. # Original shapes and lists of packed shapes for different axes.
  28. shapes = [
  29. ((0,), [(0,)]),
  30. ((10, 20, 0), [(2, 20, 0), (10, 3, 0), (10, 20, 0)]),
  31. ((10, 0, 20), [(2, 0, 20), (10, 0, 20), (10, 0, 3)]),
  32. ((0, 10, 20), [(0, 10, 20), (0, 2, 20), (0, 10, 3)]),
  33. ((20, 0, 0), [(3, 0, 0), (20, 0, 0), (20, 0, 0)]),
  34. ((0, 20, 0), [(0, 20, 0), (0, 3, 0), (0, 20, 0)]),
  35. ((0, 0, 20), [(0, 0, 20), (0, 0, 20), (0, 0, 3)]),
  36. ((0, 0, 0), [(0, 0, 0), (0, 0, 0), (0, 0, 0)]),
  37. ]
  38. for dt in '?bBhHiIlLqQ':
  39. for in_shape, out_shapes in shapes:
  40. for ax, out_shape in enumerate(out_shapes):
  41. a = np.empty(in_shape, dtype=dt)
  42. b = np.packbits(a, axis=ax)
  43. assert_equal(b.dtype, np.uint8)
  44. assert_equal(b.shape, out_shape)
  45. @pytest.mark.parametrize('bitorder', ('little', 'big'))
  46. def test_packbits_large(bitorder):
  47. # test data large enough for 16 byte vectorization
  48. a = np.array([1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0,
  49. 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1,
  50. 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0,
  51. 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1,
  52. 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
  53. 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1,
  54. 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1,
  55. 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1,
  56. 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0,
  57. 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1,
  58. 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
  59. 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1,
  60. 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0,
  61. 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0,
  62. 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0])
  63. a = a.repeat(3)
  64. for dtype in '?bBhHiIlLqQ':
  65. arr = np.array(a, dtype=dtype)
  66. b = np.packbits(arr, axis=None, bitorder=bitorder)
  67. assert_equal(b.dtype, np.uint8)
  68. r = [252, 127, 192, 3, 254, 7, 252, 0, 7, 31, 240, 0, 28, 1, 255, 252,
  69. 113, 248, 3, 255, 192, 28, 15, 192, 28, 126, 0, 224, 127, 255,
  70. 227, 142, 7, 31, 142, 63, 28, 126, 56, 227, 240, 0, 227, 128, 63,
  71. 224, 14, 56, 252, 112, 56, 255, 241, 248, 3, 240, 56, 224, 112,
  72. 63, 255, 255, 199, 224, 14, 0, 31, 143, 192, 3, 255, 199, 0, 1,
  73. 255, 224, 1, 255, 252, 126, 63, 0, 1, 192, 252, 14, 63, 0, 15,
  74. 199, 252, 113, 255, 3, 128, 56, 252, 14, 7, 0, 113, 255, 255, 142, 56, 227,
  75. 129, 248, 227, 129, 199, 31, 128]
  76. if bitorder == 'big':
  77. assert_array_equal(b, r)
  78. # equal for size being multiple of 8
  79. assert_array_equal(np.unpackbits(b, bitorder=bitorder)[:-4], a)
  80. # check last byte of different remainders (16 byte vectorization)
  81. b = [np.packbits(arr[:-i], axis=None)[-1] for i in range(1, 16)]
  82. assert_array_equal(b, [128, 128, 128, 31, 30, 28, 24, 16, 0, 0, 0, 199,
  83. 198, 196, 192])
  84. arr = arr.reshape(36, 25)
  85. b = np.packbits(arr, axis=0)
  86. assert_equal(b.dtype, np.uint8)
  87. assert_array_equal(b, [[190, 186, 178, 178, 150, 215, 87, 83, 83, 195,
  88. 199, 206, 204, 204, 140, 140, 136, 136, 8, 40, 105,
  89. 107, 75, 74, 88],
  90. [72, 216, 248, 241, 227, 195, 202, 90, 90, 83,
  91. 83, 119, 127, 109, 73, 64, 208, 244, 189, 45,
  92. 41, 104, 122, 90, 18],
  93. [113, 120, 248, 216, 152, 24, 60, 52, 182, 150,
  94. 150, 150, 146, 210, 210, 246, 255, 255, 223,
  95. 151, 21, 17, 17, 131, 163],
  96. [214, 210, 210, 64, 68, 5, 5, 1, 72, 88, 92,
  97. 92, 78, 110, 39, 181, 149, 220, 222, 218, 218,
  98. 202, 234, 170, 168],
  99. [0, 128, 128, 192, 80, 112, 48, 160, 160, 224,
  100. 240, 208, 144, 128, 160, 224, 240, 208, 144,
  101. 144, 176, 240, 224, 192, 128]])
  102. b = np.packbits(arr, axis=1)
  103. assert_equal(b.dtype, np.uint8)
  104. assert_array_equal(b, [[252, 127, 192, 0],
  105. [ 7, 252, 15, 128],
  106. [240, 0, 28, 0],
  107. [255, 128, 0, 128],
  108. [192, 31, 255, 128],
  109. [142, 63, 0, 0],
  110. [255, 240, 7, 0],
  111. [ 7, 224, 14, 0],
  112. [126, 0, 224, 0],
  113. [255, 255, 199, 0],
  114. [ 56, 28, 126, 0],
  115. [113, 248, 227, 128],
  116. [227, 142, 63, 0],
  117. [ 0, 28, 112, 0],
  118. [ 15, 248, 3, 128],
  119. [ 28, 126, 56, 0],
  120. [ 56, 255, 241, 128],
  121. [240, 7, 224, 0],
  122. [227, 129, 192, 128],
  123. [255, 255, 254, 0],
  124. [126, 0, 224, 0],
  125. [ 3, 241, 248, 0],
  126. [ 0, 255, 241, 128],
  127. [128, 0, 255, 128],
  128. [224, 1, 255, 128],
  129. [248, 252, 126, 0],
  130. [ 0, 7, 3, 128],
  131. [224, 113, 248, 0],
  132. [ 0, 252, 127, 128],
  133. [142, 63, 224, 0],
  134. [224, 14, 63, 0],
  135. [ 7, 3, 128, 0],
  136. [113, 255, 255, 128],
  137. [ 28, 113, 199, 0],
  138. [ 7, 227, 142, 0],
  139. [ 14, 56, 252, 0]])
  140. arr = arr.T.copy()
  141. b = np.packbits(arr, axis=0)
  142. assert_equal(b.dtype, np.uint8)
  143. assert_array_equal(b, [[252, 7, 240, 255, 192, 142, 255, 7, 126, 255,
  144. 56, 113, 227, 0, 15, 28, 56, 240, 227, 255,
  145. 126, 3, 0, 128, 224, 248, 0, 224, 0, 142, 224,
  146. 7, 113, 28, 7, 14],
  147. [127, 252, 0, 128, 31, 63, 240, 224, 0, 255,
  148. 28, 248, 142, 28, 248, 126, 255, 7, 129, 255,
  149. 0, 241, 255, 0, 1, 252, 7, 113, 252, 63, 14,
  150. 3, 255, 113, 227, 56],
  151. [192, 15, 28, 0, 255, 0, 7, 14, 224, 199, 126,
  152. 227, 63, 112, 3, 56, 241, 224, 192, 254, 224,
  153. 248, 241, 255, 255, 126, 3, 248, 127, 224, 63,
  154. 128, 255, 199, 142, 252],
  155. [0, 128, 0, 128, 128, 0, 0, 0, 0, 0, 0, 128, 0,
  156. 0, 128, 0, 128, 0, 128, 0, 0, 0, 128, 128,
  157. 128, 0, 128, 0, 128, 0, 0, 0, 128, 0, 0, 0]])
  158. b = np.packbits(arr, axis=1)
  159. assert_equal(b.dtype, np.uint8)
  160. assert_array_equal(b, [[190, 72, 113, 214, 0],
  161. [186, 216, 120, 210, 128],
  162. [178, 248, 248, 210, 128],
  163. [178, 241, 216, 64, 192],
  164. [150, 227, 152, 68, 80],
  165. [215, 195, 24, 5, 112],
  166. [ 87, 202, 60, 5, 48],
  167. [ 83, 90, 52, 1, 160],
  168. [ 83, 90, 182, 72, 160],
  169. [195, 83, 150, 88, 224],
  170. [199, 83, 150, 92, 240],
  171. [206, 119, 150, 92, 208],
  172. [204, 127, 146, 78, 144],
  173. [204, 109, 210, 110, 128],
  174. [140, 73, 210, 39, 160],
  175. [140, 64, 246, 181, 224],
  176. [136, 208, 255, 149, 240],
  177. [136, 244, 255, 220, 208],
  178. [ 8, 189, 223, 222, 144],
  179. [ 40, 45, 151, 218, 144],
  180. [105, 41, 21, 218, 176],
  181. [107, 104, 17, 202, 240],
  182. [ 75, 122, 17, 234, 224],
  183. [ 74, 90, 131, 170, 192],
  184. [ 88, 18, 163, 168, 128]])
  185. # result is the same if input is multiplied with a nonzero value
  186. for dtype in 'bBhHiIlLqQ':
  187. arr = np.array(a, dtype=dtype)
  188. rnd = np.random.randint(low=np.iinfo(dtype).min,
  189. high=np.iinfo(dtype).max, size=arr.size,
  190. dtype=dtype)
  191. rnd[rnd == 0] = 1
  192. arr *= rnd.astype(dtype)
  193. b = np.packbits(arr, axis=-1)
  194. assert_array_equal(np.unpackbits(b)[:-4], a)
  195. assert_raises(TypeError, np.packbits, np.array(a, dtype=float))
  196. def test_packbits_very_large():
  197. # test some with a larger arrays gh-8637
  198. # code is covered earlier but larger array makes crash on bug more likely
  199. for s in range(950, 1050):
  200. for dt in '?bBhHiIlLqQ':
  201. x = np.ones((200, s), dtype=bool)
  202. np.packbits(x, axis=1)
  203. def test_unpackbits():
  204. # Copied from the docstring.
  205. a = np.array([[2], [7], [23]], dtype=np.uint8)
  206. b = np.unpackbits(a, axis=1)
  207. assert_equal(b.dtype, np.uint8)
  208. assert_array_equal(b, np.array([[0, 0, 0, 0, 0, 0, 1, 0],
  209. [0, 0, 0, 0, 0, 1, 1, 1],
  210. [0, 0, 0, 1, 0, 1, 1, 1]]))
  211. def test_pack_unpack_order():
  212. a = np.array([[2], [7], [23]], dtype=np.uint8)
  213. b = np.unpackbits(a, axis=1)
  214. assert_equal(b.dtype, np.uint8)
  215. b_little = np.unpackbits(a, axis=1, bitorder='little')
  216. b_big = np.unpackbits(a, axis=1, bitorder='big')
  217. assert_array_equal(b, b_big)
  218. assert_array_equal(a, np.packbits(b_little, axis=1, bitorder='little'))
  219. assert_array_equal(b[:,::-1], b_little)
  220. assert_array_equal(a, np.packbits(b_big, axis=1, bitorder='big'))
  221. assert_raises(ValueError, np.unpackbits, a, bitorder='r')
  222. assert_raises(TypeError, np.unpackbits, a, bitorder=10)
  223. def test_unpackbits_empty():
  224. a = np.empty((0,), dtype=np.uint8)
  225. b = np.unpackbits(a)
  226. assert_equal(b.dtype, np.uint8)
  227. assert_array_equal(b, np.empty((0,)))
  228. def test_unpackbits_empty_with_axis():
  229. # Lists of packed shapes for different axes and unpacked shapes.
  230. shapes = [
  231. ([(0,)], (0,)),
  232. ([(2, 24, 0), (16, 3, 0), (16, 24, 0)], (16, 24, 0)),
  233. ([(2, 0, 24), (16, 0, 24), (16, 0, 3)], (16, 0, 24)),
  234. ([(0, 16, 24), (0, 2, 24), (0, 16, 3)], (0, 16, 24)),
  235. ([(3, 0, 0), (24, 0, 0), (24, 0, 0)], (24, 0, 0)),
  236. ([(0, 24, 0), (0, 3, 0), (0, 24, 0)], (0, 24, 0)),
  237. ([(0, 0, 24), (0, 0, 24), (0, 0, 3)], (0, 0, 24)),
  238. ([(0, 0, 0), (0, 0, 0), (0, 0, 0)], (0, 0, 0)),
  239. ]
  240. for in_shapes, out_shape in shapes:
  241. for ax, in_shape in enumerate(in_shapes):
  242. a = np.empty(in_shape, dtype=np.uint8)
  243. b = np.unpackbits(a, axis=ax)
  244. assert_equal(b.dtype, np.uint8)
  245. assert_equal(b.shape, out_shape)
  246. def test_unpackbits_large():
  247. # test all possible numbers via comparison to already tested packbits
  248. d = np.arange(277, dtype=np.uint8)
  249. assert_array_equal(np.packbits(np.unpackbits(d)), d)
  250. assert_array_equal(np.packbits(np.unpackbits(d[::2])), d[::2])
  251. d = np.tile(d, (3, 1))
  252. assert_array_equal(np.packbits(np.unpackbits(d, axis=1), axis=1), d)
  253. d = d.T.copy()
  254. assert_array_equal(np.packbits(np.unpackbits(d, axis=0), axis=0), d)
  255. class TestCount():
  256. x = np.array([
  257. [1, 0, 1, 0, 0, 1, 0],
  258. [0, 1, 1, 1, 0, 0, 0],
  259. [0, 0, 1, 0, 0, 1, 1],
  260. [1, 1, 0, 0, 0, 1, 1],
  261. [1, 0, 1, 0, 1, 0, 1],
  262. [0, 0, 1, 1, 1, 0, 0],
  263. [0, 1, 0, 1, 0, 1, 0],
  264. ], dtype=np.uint8)
  265. padded1 = np.zeros(57, dtype=np.uint8)
  266. padded1[:49] = x.ravel()
  267. padded1b = np.zeros(57, dtype=np.uint8)
  268. padded1b[:49] = x[::-1].copy().ravel()
  269. padded2 = np.zeros((9, 9), dtype=np.uint8)
  270. padded2[:7, :7] = x
  271. @pytest.mark.parametrize('bitorder', ('little', 'big'))
  272. @pytest.mark.parametrize('count', chain(range(58), range(-1, -57, -1)))
  273. def test_roundtrip(self, bitorder, count):
  274. if count < 0:
  275. # one extra zero of padding
  276. cutoff = count - 1
  277. else:
  278. cutoff = count
  279. # test complete invertibility of packbits and unpackbits with count
  280. packed = np.packbits(self.x, bitorder=bitorder)
  281. unpacked = np.unpackbits(packed, count=count, bitorder=bitorder)
  282. assert_equal(unpacked.dtype, np.uint8)
  283. assert_array_equal(unpacked, self.padded1[:cutoff])
  284. @pytest.mark.parametrize('kwargs', [
  285. {}, {'count': None},
  286. ])
  287. def test_count(self, kwargs):
  288. packed = np.packbits(self.x)
  289. unpacked = np.unpackbits(packed, **kwargs)
  290. assert_equal(unpacked.dtype, np.uint8)
  291. assert_array_equal(unpacked, self.padded1[:-1])
  292. @pytest.mark.parametrize('bitorder', ('little', 'big'))
  293. # delta==-1 when count<0 because one extra zero of padding
  294. @pytest.mark.parametrize('count', chain(range(8), range(-1, -9, -1)))
  295. def test_roundtrip_axis(self, bitorder, count):
  296. if count < 0:
  297. # one extra zero of padding
  298. cutoff = count - 1
  299. else:
  300. cutoff = count
  301. packed0 = np.packbits(self.x, axis=0, bitorder=bitorder)
  302. unpacked0 = np.unpackbits(packed0, axis=0, count=count,
  303. bitorder=bitorder)
  304. assert_equal(unpacked0.dtype, np.uint8)
  305. assert_array_equal(unpacked0, self.padded2[:cutoff, :self.x.shape[1]])
  306. packed1 = np.packbits(self.x, axis=1, bitorder=bitorder)
  307. unpacked1 = np.unpackbits(packed1, axis=1, count=count,
  308. bitorder=bitorder)
  309. assert_equal(unpacked1.dtype, np.uint8)
  310. assert_array_equal(unpacked1, self.padded2[:self.x.shape[0], :cutoff])
  311. @pytest.mark.parametrize('kwargs', [
  312. {}, {'count': None},
  313. {'bitorder' : 'little'},
  314. {'bitorder': 'little', 'count': None},
  315. {'bitorder' : 'big'},
  316. {'bitorder': 'big', 'count': None},
  317. ])
  318. def test_axis_count(self, kwargs):
  319. packed0 = np.packbits(self.x, axis=0)
  320. unpacked0 = np.unpackbits(packed0, axis=0, **kwargs)
  321. assert_equal(unpacked0.dtype, np.uint8)
  322. if kwargs.get('bitorder', 'big') == 'big':
  323. assert_array_equal(unpacked0, self.padded2[:-1, :self.x.shape[1]])
  324. else:
  325. assert_array_equal(unpacked0[::-1, :], self.padded2[:-1, :self.x.shape[1]])
  326. packed1 = np.packbits(self.x, axis=1)
  327. unpacked1 = np.unpackbits(packed1, axis=1, **kwargs)
  328. assert_equal(unpacked1.dtype, np.uint8)
  329. if kwargs.get('bitorder', 'big') == 'big':
  330. assert_array_equal(unpacked1, self.padded2[:self.x.shape[0], :-1])
  331. else:
  332. assert_array_equal(unpacked1[:, ::-1], self.padded2[:self.x.shape[0], :-1])
  333. def test_bad_count(self):
  334. packed0 = np.packbits(self.x, axis=0)
  335. assert_raises(ValueError, np.unpackbits, packed0, axis=0, count=-9)
  336. packed1 = np.packbits(self.x, axis=1)
  337. assert_raises(ValueError, np.unpackbits, packed1, axis=1, count=-9)
  338. packed = np.packbits(self.x)
  339. assert_raises(ValueError, np.unpackbits, packed, count=-57)