PythonLibrary Python NumPy 2019年 1月 15日
ブロックごとにアクセスをするイテレータのテストを行いたい. 例として,ブロックスクランブルを計算する generate_with_block_trans のテストを行う.
with such.A('MonoImage class') as it:
@it.should('exec block scramble')
def test():
### vector test
org_vec = MonoImage(np.arange(0, 9), 8)
index = MonoImage.create_with_array([2, 0, 3, 1], np.int32)
correct_vec = MonoImage.create_with_array([4, 5, 0, 1, 6, 7, 2, 3, 8], np.int, 8)
ans_vec = org_vec.generate_with_block_trans(index, 1, 2)
it.assertEqual(ans_vec, correct_vec)
rev_vec = ans_vec.generate_with_reverse_block_trans(index, 1, 2)
it.assertEqual(rev_vec, org_vec)
org_vec = MonoImage(np.arange(0, 9), 8)
index = MonoImage.create_with_array([2, 0, 3, 1], np.int32)
correct_vec = MonoImage.create_with_array([4, 5, 0, 1, 6, 7, 2, 3, 8], np.int, 8)
ans_vec = org_vec.generate_with_block_trans(index, 1, 2)
rev_vec = ans_vec.generate_with_reverse_block_trans(index, 1, 2)
class MonoImage:
(中略)
def generate_with_block_trans(self, index, br, bc):
ans = self.generate_with_copy()
if self.ndim == 1:
for (pi, mi) in zip(index.pixel_iterator(), ans.block_iterator(br, bc, br, bc, False)):
vc = pi.value * bc
bi.value = self._array[vc:vc+bc]
return ans
ans = self.generate_with_copy()
if self.ndim == 1:
for (pi, mi) in zip(index.pixel_iterator(), ans.block_iterator(br, bc, br, bc, False)):
vc = pi.value * bc
bi.value = self._array[vc:vc+bc]
return ans
def generate_with_copy(self):
return MonoImage(self._array.copy(), self.bits, self.signed)
def block_iterator(self, br, bc, sr, sc, is_small_ok):
return MonoImageBlockIterator(self, br, bc, sr, sc, is_small_ok)
class MonoImageBlockIterator:
def __init__(self, mono_image, br, bc, sr, sc, is_small_ok):
self._mono_image = mono_image
self._br = br
self._bc = bc
self._sr = sr
self._sc = sc
self._is_small_ok = is_small_ok
self._width = mono_image.width
self._height = mono_image.height
self._f = self.vector_iterator_func
self._getter = self.vector_getter_func
self._setter = self.vector_setter_func
def __iter__(self):
return self._f()
class MonoImageBlockIterator:
(中略)
def vector_iterator_func(self):
self._nowi = 0
while (self._nowi != -1):
remain = self._width - self._nowi
self._len = self._bc if remain > self._bc else remain
if self._len == self._bc or self._is_small_ok:
yield self
self._nowi += self._sc
if self._nowi >= self._width:
self._nowi = -1
self._nowi = 0
while (self._nowi != -1):
remain = self._width - self._nowi
self._len = self._bc if remain > self._bc else remain
if self._len == self._bc or self._is_small_ok:
yield self
self._nowi += self._sc
if self._nowi >= self._width:
self._nowi = -1
@property
def value(self):
return self._getter()
@value.setter
def value(self, v):
self._setter(v)
def vector_getter_func(self):
return self._mono_image._array[self._nowi:self._nowi+self._len]
def vector_setter_func(self, nda):
self._mono_image._array[self._nowi:self._nowi+self._len] = nda
class MonoImage:
(中略)
def generate_with_reverse_block_trans(self, index, br, bc):
reverse_index = index.generate_with_zeros()
i = 0
for pi in index.pixel_iterator():
reverse_index.set_value_at(i, pi.value)
i += 1
return self.generate_with_block_trans(reverse_index, br, bc)
def set_value_at(self, v, p):
self._array[p] = v
### vector test (without edge)
org_vec.delete_self(-1, None)
correct_vec.delete_self(-1, None)
ans_vec = org_vec.generate_with_block_trans(index, 1, 2)
it.assertEqual(ans_vec, correct_vec)
rev_vec = ans_vec.generate_with_reverse_block_trans(index, 1, 2)
it.assertEqual(rev_vec, org_vec)
class MonoImage:
def delete_self(self, obj, axis):
self._array = np.delete(self._array, obj, axis)
return self
### raise exception when index size is wrong
org_vec.delete_self(-1, None)
with it.assertRaises(IndexError):
org_vec.generate_with_block_trans(index, 1, 2)
class MonoImage:
(中略)
def generate_with_block_trans(self, index, br, bc):
if int(self.width / bc) * int(self.height / br) != index.width:
raise IndexError('wrong index length')
(後略)
長くなったので今日はここまで.