💡
この記事は Middleman 時代に書いた古いものです。記録のため、astro-notion-blog に移行していますが、あまり参考にしないでください。
ブロックベースのイテレータのテスト(matrix 版)
-
generate_with_block_trans のテストに行列のテストを追記する. obj.generate_with_block_trans は index とブロックサイズを渡し,index にしたがってブロックの入れ替えを行う. 今回は,ブロックサイズを2行3列としている.
with such.A('MonoImage class') as it: @it.should('exec block scramble') def test(): (中略) ### matrix test org_mat = MonoImage(np.arange(0, 35).reshape(5, 7), 8) correct_mat = MonoImage.create_with_array( [ [14, 15, 16, 0, 1, 2, 6], [21, 22, 23, 7, 8, 9, 13], [17, 18, 19, 3, 4, 5, 20], [24, 25, 26, 10, 11, 12, 27], [28, 29, 30, 31, 32, 33, 34], ], np.int, 8) ans_mat = org_mat.generate_with_block_trans(index, 2, 3) it.assertEqual(ans_mat, correct_mat) rev_mat = ans_mat.generate_with_reverse_block_trans(index, 2, 3) it.assertEqual(rev_mat, org_mat)
generate_with_block_trans の実装の修正
-
generate_with_block_trans に matrix の実装を追加する. ベクトルと異なり br, bc のサイズの行列を setter property に渡している.
class MonoImage: def generate_with_block_trans(self, index, br, bc): ans = self.generate_with_copy() if self.ndim == 1: (中略) else: nx = int(self.width / bc) ny = int(self.height / br) for (pi, bi) in zip(index.pixel_iterator(), ans.block_iterator(br, bc, br, bc, False)): v = pi.value vr = int(v / nx) * br vc = (v % nx) * bc bi.value = self._array[vr:vr+br, vc:vc+bc] return ans
MonoImageBlockIterator への追加・修正
-
__init__ の _f, _getter, _setter に matrix 系のメソッドを追記する
self._f = self.vector_iterator_func if mono_image.ndim == 1 else self.matrix_iterator_func self._getter = self.vector_getter_func if mono_image.ndim == 1 else self.matrix_getter_func self._setter = self.vector_setter_func if mono_image.ndim == 1 else self.matrix_setter_func
-
参照している matrix_iterator_func を実装する
class MonoImageBlockIterator: def matrix_iterator_func(self): self._nowr = 0 self._nowc = 0 while (self._nowr != -1): remain_r = self._height - self._nowr remain_c = self._width - self._nowc self._lenr = self._br if remain_r > self._br else remain_r self._lenc = self._bc if remain_c > self._bc else remain_c if (self._lenr == self._br and self._lenc == self._bc) or self._is_small_ok: yield self self._nowc += self._sc if self._nowc >= self._width: self._nowc = 0 self._nowr += self._sr if self._nowr >= self._height: self._nowr = -1
-
同様に matrix_getter_func も実装する.
def matrix_getter_func(self): return self._mono_image._array[self._nowr:self._nowr+self._lenr, self._nowc:self._nowc+self._lenc]
-
同様に matrix_setter_func も実装する.
def matrix_setter_func(self, nda): self._mono_image._array[self._nowr:self._nowr+self._lenr, self._nowc:self._nowc+self._lenc] = nda
- これでテストが全て通過した.
端数がない場合のテスト
-
ベクトルの場合と同様,念のため端数が存在しない場合にもうまく動作することを確認するために,長さを 8 に変更した場合のテストも追加しておく. np.delete で org_mat と correct_mat の最後の列要素および行要素を削る. これによって,両行列とも大きさが 4 行 6 列 (ブロックサイズ 2 行 3 列 の倍数)となり,端数がなくなる.
### matrix test (without edge) np.delete(org_mat._array, -1, -1) np.delete(correct_mat._array, -1, -1) ans_mat = org_mat.generate_with_block_trans(index, 2, 3) it.assertEqual(ans_mat, correct_mat) rev_mat = ans_mat.generate_with_reverse_block_trans(index, 2, 3) it.assertEqual(rev_mat, org_mat)
- テストを追加しても,テストはそのまま成功した.これで行列のブロックスクランブルのテストは終わりにする.
index の数が一致しない時の例外のテスト
-
さらにベクトルの時と同様に index の数とブロック数が一致しないときには例外を出したい. さらに行列の大きさを 5 行 3 列 に減らすと,index の長さ 4 と一致しなくなる. このときに例外が発生するかどうかをテストする.
### raise exception when index size is wrong org_mat.delete_self(-1, 0).delete_self(-1, 1) with it.assertRaises(IndexError): org_mat.generate_with_block_trans(index, 2, 3)
- すでに例外処理を追加しているので,このテストはそのまま動作する.
長くなったので今日はここまで.