from __future__ import print_function, division, absolute_import import warnings import sys # unittest only added in 3.4 self.subTest() if sys.version_info[0] < 3 or sys.version_info[1] < 4: import unittest2 as unittest else: import unittest # unittest.mock is not available in 2.7 (though unittest2 might contain it?) try: import unittest.mock as mock except ImportError: import mock import numpy as np from imgaug import dtypes as iadt from imgaug.testutils import ensure_deprecation_warning class Test_normalize_dtypes(unittest.TestCase): @mock.patch("imgaug.dtypes.normalize_dtype") def test_single_non_list(self, mock_nd): mock_nd.return_value = "foo" dtypes = iadt.normalize_dtypes("int16") assert dtypes == ["foo"] assert mock_nd.call_count == 1 assert mock_nd.call_args_list[0][0][0] == "int16" def test_single_dtype(self): dtypes = iadt.normalize_dtypes(np.dtype("int16")) assert isinstance(dtypes, list) assert len(dtypes) == 1 assert isinstance(dtypes[0], np.dtype) assert dtypes[0].name == "int16" def test_empty_list(self): dtypes = iadt.normalize_dtypes([]) assert isinstance(dtypes, list) assert len(dtypes) == 0 @mock.patch("imgaug.dtypes.normalize_dtype") def test_list_of_dtype_names(self, mock_nd): mock_nd.return_value = "foo" dtypes = iadt.normalize_dtypes(["int16", "int32"]) assert dtypes == ["foo", "foo"] assert mock_nd.call_count == 2 assert mock_nd.call_args_list[0][0][0] == "int16" assert mock_nd.call_args_list[1][0][0] == "int32" class Test_normalize_dtype(unittest.TestCase): def test_dtype(self): dtype = iadt.normalize_dtype(np.dtype("int16")) assert isinstance(dtype, np.dtype) assert dtype.name == "int16" def test_dtype_name(self): dtype = iadt.normalize_dtype("int16") assert isinstance(dtype, np.dtype) assert dtype.name == "int16" def test_dtype_name_short(self): dtype = iadt.normalize_dtype("i2") assert isinstance(dtype, np.dtype) assert dtype.name == "int16" def test_dtype_function(self): dtype = iadt.normalize_dtype(np.int16) assert isinstance(dtype, np.dtype) assert dtype.name == "int16" def test_ndarray(self): arr = np.zeros((1,), dtype=np.int16) dtype = iadt.normalize_dtype(arr) assert isinstance(dtype, np.dtype) assert dtype.name == "int16" def test_numpy_scalar(self): scalar = np.int16(0) dtype = iadt.normalize_dtype(scalar) assert isinstance(dtype, np.dtype) assert dtype.name == "int16" # change_dtype_() is already indirectly tested via Test_change_dtypes_(), # so were don't have to be very thorough here class Test_change_dtype_(unittest.TestCase): def test_no_clip_no_round(self): arr = np.array([[0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0]], dtype=np.float32) dtype = np.int8 observed = iadt.change_dtype_(np.copy(arr), dtype, clip=False, round=False) expected = np.array([[0, 0, 0, -128+1-1, 127-1+1]], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) def test_clip_and_round(self): arr = np.array([[0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0]], dtype=np.float32) dtype = np.int8 observed = iadt.restore_dtypes_(np.copy(arr), dtype) expected = np.array([[0, 0, 1, 127, -128]], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) def test_dtype_not_changed(self): arr = np.array([[-128, -1, 0, 1, 127]], dtype=np.int8) dtype = np.int8 observed = iadt.restore_dtypes_(arr, dtype, clip=False, round=False) assert observed is arr @mock.patch('numpy.round') def test_no_round_if_dtype_not_changed(self, mock_round): arr = np.array([[-128, -1, 0, 1, 127]], dtype=np.int8) dtype = np.int8 observed = iadt.restore_dtypes_(arr, dtype, clip=False) assert observed is arr assert mock_round.call_count == 0 def test_round_float_dtypes(self): arr = np.array([[-128, -1.1, 0.7, 1.1, 127]], dtype=np.float32) dtype = np.int8 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False) expected = np.array([[-128, -1, 1, 1, 127]], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) @mock.patch('numpy.round') def test_dont_round_non_float_dtypes(self, mock_round): arr = np.array([[-128, -1, 0, 1, 127]], dtype=np.int8) dtype = np.float32 _ = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False) assert mock_round.call_count == 0 def test_int16_to_int8(self): arr = np.zeros((1,), dtype=np.int16) + 1 observed = iadt.change_dtype_(arr, np.int8, clip=False, round=False) assert observed.shape == (1,) assert observed.dtype.name == "int8" assert np.all(observed == 1) def test_int16_to_int8_with_overflow(self): arr = np.zeros((1,), dtype=np.int16) + 128 observed = iadt.change_dtype_(arr, np.int8, clip=False, round=False) assert observed.shape == (1,) assert observed.dtype.name == "int8" assert np.all(observed == -128) def test_float32_to_int8(self): arr = np.zeros((1,), dtype=np.int32) + 1 observed = iadt.change_dtype_(arr, np.int8, clip=False, round=False) assert observed.shape == (1,) assert observed.dtype.name == "int8" assert np.all(observed == 1) def test_float32_to_int8_with_overflow(self): arr = np.zeros((1,), dtype=np.int32) + 1 observed = iadt.change_dtype_(arr, np.int8, clip=False, round=False) assert observed.shape == (1,) assert observed.dtype.name == "int8" assert np.all(observed == 1) def test_dtype_given_as_string(self): arr = np.zeros((1,), dtype=np.int8) + 1 observed = iadt.change_dtype_(arr, "int16", clip=False, round=False) assert observed.shape == (1,) assert observed.dtype.name == "int16" assert np.all(observed == 1) class Test_change_dtypes_(unittest.TestCase): def test_array_input_single_dtype_no_clip_no_round(self): arr = np.array([[0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0]], dtype=np.float32) dtype = np.int8 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False, round=False) expected = np.array([[0, 0, 0, -128+1-1, 127-1+1]], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) def test_array_input_single_dtype_with_clip_no_round(self): arr = np.array([[0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0]], dtype=np.float32) dtype = np.int8 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=True, round=False) expected = np.array([[0, 0, 0, 127, -128]], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) def test_array_input_single_dtype_no_clip_with_round(self): arr = np.array([[0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0]], dtype=np.float32) dtype = np.int8 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False, round=True) expected = np.array([[0, 0, 1, -128+1-1, 127-1+1]], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) def test_array_input_fail_if_many_different_dtypes(self): arr = np.array([ [0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0], [0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0], ], dtype=np.float32) dtypes = [np.int8, np.int16] with self.assertRaises(AssertionError) as context: _observed = iadt.restore_dtypes_(np.copy(arr), dtypes, clip=False, round=False) assert ( "or an iterable of N times the *same* dtype" in str(context.exception) ) def test_array_input_many_dtypes_no_clip_no_round(self): arr = np.array([ [0.0, 0.1, 0.9, 127.0+0.0, -128.0-0.0], [0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0], ], dtype=np.float32) dtypes = [np.int8, np.int8] observed = iadt.restore_dtypes_(np.copy(arr), dtypes, clip=False, round=False) expected = np.array([ [0, 0, 0, 127, -128], [0, 0, 0, -128+1-1, 127-1+1] ], dtype=np.int8) assert observed.dtype.name == "int8" assert np.array_equal(observed, expected) def test_empty_array_input(self): arr = np.zeros((0, 5), dtype=np.float32) dtypes = np.int8 observed = iadt.restore_dtypes_(np.copy(arr), dtypes, clip=False, round=False) assert observed.dtype.name == "int8" assert observed.shape == (0, 5) def test_empty_list_input(self): arrs = [] dtypes = np.int8 observed = iadt.restore_dtypes_(arrs, dtypes, clip=False, round=False) assert len(observed) == 0 def test_many_items_list_input_single_dtype(self): arrs = [ np.array([0.0, 0.1, 0.9, 127.0+0.0, -128.0-0.0], dtype=np.float32), np.array([0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0], dtype=np.float32) ] dtypes = np.int8 observed = iadt.restore_dtypes_( [np.copy(arr) for arr in arrs], dtypes, clip=False, round=False) expected = [ np.array([0, 0, 0, 127, -128], dtype=np.int8), np.array([0, 0, 0, -128+1-1, 127-1+1], dtype=np.int8) ] assert len(observed) == 2 assert observed[0].dtype.name == "int8" assert observed[1].dtype.name == "int8" assert np.array_equal(observed[0], expected[0]) assert np.array_equal(observed[1], expected[1]) def test_many_items_list_input_many_dtypes(self): arrs = [ np.array([0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0], dtype=np.float32), np.array([0.0, 0.1, 0.9, 127.0+1.0, -128.0-1.0], dtype=np.float32) ] dtypes = [np.int8, np.int16] observed = iadt.restore_dtypes_( [np.copy(arr) for arr in arrs], dtypes, clip=False, round=False) expected = [ np.array([0, 0, 0, -128+1-1, 127-1+1], dtype=np.int8), np.array([0, 0, 0, 127+1, -128-1], dtype=np.int16) ] assert len(observed) == 2 assert observed[0].dtype.name == "int8" assert observed[1].dtype.name == "int16" assert np.array_equal(observed[0], expected[0]) assert np.array_equal(observed[1], expected[1]) def test_invalid_input(self): arr = False with self.assertRaises(Exception) as context: _ = iadt.restore_dtypes_(arr, np.int8) assert "Expected numpy array or " in str(context.exception) def test_int_to_float(self): arr = np.array([[-100, -1, 0, 1, 100]], dtype=np.int8) dtype = np.float32 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False, round=False) expected = np.array([[-100.0, -1.0, 0.0, 1.0, 100.0]], dtype=np.float32) assert observed.dtype.name == "float32" assert np.allclose(observed, expected) def test_increase_float_resolution(self): arr = np.array([[-100.0, -1.0, 0.0, 1.0, 100.0]], dtype=np.float32) dtype = np.float64 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False, round=False) expected = np.array([[-100.0, -1.0, 0.0, 1.0, 100.0]], dtype=np.float32) assert observed.dtype.name == "float64" assert np.allclose(observed, expected) def test_int_to_uint(self): arr = np.array([[-100, -1, 0, 1, 100]], dtype=np.int8) dtype = np.uint8 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=False, round=False) expected = np.array([[255-100+1, 255-1+1, 0, 1, 100]], dtype=np.uint8) assert observed.dtype.name == "uint8" assert np.allclose(observed, expected) def test_int_to_uint_with_clip(self): arr = np.array([[-100, -1, 0, 1, 100]], dtype=np.int8) dtype = np.uint8 observed = iadt.restore_dtypes_(np.copy(arr), dtype, clip=True, round=False) expected = np.array([[0, 0, 0, 1, 100]], dtype=np.uint8) assert observed.dtype.name == "uint8" assert np.allclose(observed, expected) # TODO is the copy_* function still used anywhere class Test_copy_dtypes_for_restore(unittest.TestCase): def test_images_as_list(self): # TODO using dtype=np.bool is causing this to fail as it ends up # being instead of . # Any problems from that for the library? images = [ np.zeros((1, 1, 3), dtype=np.uint8), np.zeros((10, 16, 3), dtype=np.float32), np.zeros((20, 10, 6), dtype=np.int32) ] dtypes_copy = iadt.copy_dtypes_for_restore(images, force_list=False) assert np.all([ dtype_observed.name == dtype_expected for dtype_observed, dtype_expected in zip( dtypes_copy, ["uint8", "float32", "int32"] ) ]) def test_images_as_single_array(self): dts = ["uint8", "float32", "int32"] for dt in dts: with self.subTest(dtype=dt): images = np.zeros((10, 16, 32, 3), dtype=dt) dtypes_copy = iadt.copy_dtypes_for_restore(images) assert isinstance(dtypes_copy, np.dtype) assert dtypes_copy.name == dt def test_images_as_single_array_force_list(self): dts = ["uint8", "float32", "int32"] for dt in dts: with self.subTest(dtype=dt): images = np.zeros((10, 16, 32, 3), dtype=dt) dtypes_copy = iadt.copy_dtypes_for_restore(images, force_list=True) assert isinstance(dtypes_copy, list) assert np.all([dtype_i.name == dt for dtype_i in dtypes_copy]) class Test_increase_itemsize_of_dtype(unittest.TestCase): def test_factor_is_1(self): dts = [ np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64, np.float16, np.float32, np.float64 ] for dt in dts: dt = np.dtype(dt) with self.subTest(dtype=dt.name): dt_increased = iadt.increase_itemsize_of_dtype(dt, 1) assert dt_increased.name == dt.name def test_factor_is_2(self): dts = [ np.int8, np.int16, np.int32, np.uint8, np.uint16, np.uint32, np.float16, np.float32 ] expecteds = [ np.int16, np.int32, np.int64, np.uint16, np.uint32, np.uint64, np.float32, np.float64 ] for dt, expected in zip(dts, expecteds): dt = np.dtype(dt) expected = np.dtype(expected) with self.subTest(dtype=dt.name): dt_increased = iadt.increase_itemsize_of_dtype(dt, 2) assert dt_increased.name == expected.name def test_dtype_as_string(self): dt_names = [ "int8", "int16", "int32", "uint8", "uint16", "uint32", "float16", "float32" ] expecteds = [ np.int16, np.int32, np.int64, np.uint16, np.uint32, np.uint64, np.float32, np.float64 ] for dt_name, expected in zip(dt_names, expecteds): expected = np.dtype(expected) with self.subTest(dtype=dt_name): dt_increased = iadt.increase_itemsize_of_dtype(dt_name, 2) assert dt_increased.name == expected.name def test_unknown_dtype(self): with self.assertRaises(TypeError) as context: _ = iadt.increase_itemsize_of_dtype(np.uint64, 2) assert ( "Unable to create a numpy dtype matching" in str(context.exception)) class Test_get_minimal_dtype(unittest.TestCase): def test_with_dtype_function(self): dt_funcs = [ np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64, np.float16, np.float32, np.float64, np.bool_ ] for dt_func in dt_funcs: with self.subTest(dtype=np.dtype(dt_func).name): inputs = [dt_func] promoted_dt = iadt.get_minimal_dtype(inputs) assert promoted_dt.name == np.dtype(dt_func).name def test_with_lists_of_identical_dtypes(self): dts = [ np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64, np.float16, np.float32, np.float64, np.bool_ ] for dt in dts: dt = np.dtype(dt) for length in [1, 2, 3]: with self.subTest(dtype=dt.name, length=length): inputs = [dt for _ in range(length)] promoted_dt = iadt.get_minimal_dtype(inputs) assert promoted_dt.name == dt.name def test_with_lists_of_identical_dtype_arrays(self): dts = [ np.int8, np.int16, np.int32, np.int64, np.uint8, np.uint16, np.uint32, np.uint64, np.float16, np.float32, np.float64, np.bool_ ] for dt in dts: dt = np.dtype(dt) for length in [1, 2, 3]: with self.subTest(dtype=dt.name, length=length): inputs = [np.zeros((1, 1, 3), dtype=dt) for _ in range(length)] promoted_dt = iadt.get_minimal_dtype(inputs) assert promoted_dt.name == dt.name def test_with_lists_of_different_arrays(self): dt_lists = [ [np.uint8, np.uint16], [np.uint8, np.uint32], [np.uint8, np.int8], [np.uint8, np.bool_], [np.int8, np.int16], [np.float16, np.float32], [np.uint8, np.float32], [np.uint8, np.int8, np.int16], [np.uint8, np.int8, np.bool_], [np.uint8, np.int8, np.float32], ] expecteds = [ np.uint16, np.uint32, np.int16, np.uint8, np.int16, np.float32, np.float32, np.int16, np.int16, np.float32 ] for dt_list, expected in zip(dt_lists, expecteds): expected = np.dtype(expected) dt_list = [np.dtype(dt) for dt in dt_list] dt_names = ", ".join([dt.name for dt in dt_list]) with self.subTest(dtypes=dt_names): promoted_dt = iadt.get_minimal_dtype(dt_list) assert promoted_dt.name == expected.name @mock.patch("imgaug.dtypes.increase_itemsize_of_dtype") def test_calls_increase_itemsize_factor(self, mock_iibf): dt = np.int8 factor = 2 _ = iadt.get_minimal_dtype([dt], factor) assert mock_iibf.call_count == 1 class Test_promote_array_dtypes_(unittest.TestCase): @mock.patch("imgaug.dtypes.get_minimal_dtype") @mock.patch("imgaug.dtypes.change_dtypes_") def test_calls_subfunctions(self, mock_cd, mock_gmd): mock_gmd.return_value = np.dtype("int16") mock_cd.return_value = "foo" arrays = [np.zeros((1,), dtype=np.int8)] observed = iadt.promote_array_dtypes_(arrays) assert mock_gmd.call_count == 1 assert mock_cd.call_count == 1 # call 0, args, arg 0, dtype 0 assert mock_gmd.call_args_list[0][0][0][0].name == "int8" assert mock_gmd.call_args_list[0][1]["increase_itemsize_factor"] == 1 assert mock_cd.call_args_list[0][0][0] is arrays assert observed == "foo" @mock.patch("imgaug.dtypes.get_minimal_dtype") @mock.patch("imgaug.dtypes.change_dtypes_") def test_calls_subfunctions_dtypes_set(self, mock_cd, mock_gmd): mock_gmd.return_value = np.dtype("int16") mock_cd.return_value = "foo" arrays = [np.zeros((1,), dtype=np.int8)] observed = iadt.promote_array_dtypes_( arrays, dtypes=["float32"]) assert mock_gmd.call_count == 1 assert mock_cd.call_count == 1 # call 0, args, arg 0, dtype 0 assert mock_gmd.call_args_list[0][0][0][0] == "float32" assert mock_gmd.call_args_list[0][1]["increase_itemsize_factor"] == 1 assert mock_cd.call_args_list[0][0][0] is arrays assert observed == "foo" @mock.patch("imgaug.dtypes.get_minimal_dtype") @mock.patch("imgaug.dtypes.change_dtypes_") def test_calls_subfunctions_increase_itemsize_factor_set(self, mock_cd, mock_gmd): mock_gmd.return_value = np.dtype("int16") mock_cd.return_value = "foo" arrays = [np.zeros((1,), dtype=np.int8)] observed = iadt.promote_array_dtypes_( arrays, increase_itemsize_factor=2) assert mock_gmd.call_count == 1 assert mock_cd.call_count == 1 # call 0, args, arg 0, dtype 0 assert mock_gmd.call_args_list[0][0][0][0].name == "int8" assert mock_gmd.call_args_list[0][1]["increase_itemsize_factor"] == 2 assert mock_cd.call_args_list[0][0][0] is arrays assert observed == "foo" def test_promote_single_array(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.promote_array_dtypes_(arr) assert observed.dtype.name == "int8" def test_promote_single_array_single_dtype_set(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.promote_array_dtypes_(arr, np.int16) assert observed.dtype.name == "int16" def test_promote_single_array_dtypes_set(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.promote_array_dtypes_(arr, [np.int16]) assert observed.dtype.name == "int16" def test_promote_single_array_increase_itemsize_factor_set(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.promote_array_dtypes_(arr, increase_itemsize_factor=2) assert observed.dtype.name == "int16" def test_promote_list_of_single_array(self): arrays = [np.zeros((1,), dtype=np.int8)] observed = iadt.promote_array_dtypes_(arrays, increase_itemsize_factor=2) assert observed[0].dtype.name == "int16" def test_promote_list_of_two_arrays(self): arrays = [np.zeros((1,), dtype=np.int8), np.zeros((1,), dtype=np.int16)] observed = iadt.promote_array_dtypes_(arrays, increase_itemsize_factor=2) assert observed[0].dtype.name == "int32" assert observed[1].dtype.name == "int32" def test_promote_list_of_two_arrays_dtypes_set(self): arrays = [np.zeros((1,), dtype=np.int8), np.zeros((1,), dtype=np.int16)] observed = iadt.promote_array_dtypes_(arrays, dtypes=[np.float32, np.float64]) assert observed[0].dtype.name == "float64" assert observed[1].dtype.name == "float64" def test_promote_list_of_three_arrays(self): arrays = [np.zeros((1,), dtype=np.int8), np.zeros((1,), dtype=np.int16), np.zeros((1,), dtype=np.uint8)] observed = iadt.promote_array_dtypes_(arrays, increase_itemsize_factor=2) assert observed[0].dtype.name == "int32" assert observed[1].dtype.name == "int32" assert observed[2].dtype.name == "int32" class Test_increase_array_resolutions_(unittest.TestCase): def test_single_array_factor_1(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.increase_array_resolutions_(arr, 1) assert observed.dtype.name == "int8" def test_single_array_factor_2(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.increase_array_resolutions_(arr, 2) assert observed.dtype.name == "int16" def test_list_of_one_array(self): arr = np.zeros((1,), dtype=np.int8) observed = iadt.increase_array_resolutions_([arr], 2) assert observed[0].dtype.name == "int16" def test_list_of_two_arrays(self): arrays = [ np.zeros((1,), dtype=np.int8), np.zeros((1,), dtype=np.int16) ] observed = iadt.increase_array_resolutions_(arrays, 2) assert observed[0].dtype.name == "int16" assert observed[1].dtype.name == "int32" class Test_get_value_range_of_dtype(unittest.TestCase): def test_bool(self): minv, center, maxv = iadt.get_value_range_of_dtype(np.dtype(bool)) assert minv == 0 assert center is None assert maxv == 1 def test_uint8_string_name(self): assert ( iadt.get_value_range_of_dtype("uint8") == iadt.get_value_range_of_dtype(np.dtype("uint8")) ) def test_uint8(self): minv, center, maxv = iadt.get_value_range_of_dtype(np.dtype("uint8")) assert minv == 0 assert np.isclose(center, 0.5*255) assert maxv == 255 def test_uint16(self): minv, center, maxv = iadt.get_value_range_of_dtype(np.dtype("uint16")) assert minv == 0 assert np.isclose(center, 0.5*65535) assert maxv == 65535 def test_int8(self): minv, center, maxv = iadt.get_value_range_of_dtype(np.dtype("int8")) assert minv == -128 assert np.isclose(center, -0.5) assert maxv == 127 def test_int16(self): minv, center, maxv = iadt.get_value_range_of_dtype(np.dtype("int16")) assert minv == -32768 assert np.isclose(center, -0.5) assert maxv == 32767 def test_float16(self): minv, center, maxv = iadt.get_value_range_of_dtype(np.dtype("float16")) assert minv < 100.0 assert np.isclose(center, 0.0) assert maxv > 100.0 # TODO extend tests towards all dtypes and actual minima/maxima of value ranges # TODO what happens if both bounds are negative, but input dtype is uint*? class Test_clip_(unittest.TestCase): def test_values_hit_lower_bound_int32(self): arr = np.int32([0, 1, 2, 3, 4, 5]) observed = iadt.clip_(arr, 0, 10) assert np.array_equal(observed, np.int32([0, 1, 2, 3, 4, 5])) def test_values_hit_lower_and_upper_bound_int32(self): arr = np.int32([0, 1, 2, 3, 4, 5]) observed = iadt.clip_(arr, 0, 5) assert np.array_equal(observed, np.int32([0, 1, 2, 3, 4, 5])) def test_values_hit_lower_bound_exceed_upper_bound_int32(self): arr = np.int32([0, 1, 2, 3, 4, 5]) observed = iadt.clip_(arr, 0, 4) assert np.array_equal(observed, np.int32([0, 1, 2, 3, 4, 4])) def test_values_exceed_lower_bound_float32(self): arr = np.float32([-1.0]) observed = iadt.clip_(arr, 0, 1) assert np.allclose(observed, np.float32([0.0])) def test_values_hit_lower_bound_float32(self): arr = np.float32([-1.0]) observed = iadt.clip_(arr, -1.0, 1) assert np.allclose(observed, np.float32([-1.0])) def test_values_hit_lower_bound_uint32(self): arr = np.uint32([0]) observed = iadt.clip_(arr, 0, 1) assert np.array_equal(observed, np.uint32([0])) def test_values_hit_upper_bound_uint32(self): arr = np.uint32([1]) observed = iadt.clip_(arr, 0, 1) assert np.array_equal(observed, np.uint32([1])) def test_values_exceed_upper_bound_uint32(self): arr = np.uint32([2]) observed = iadt.clip_(arr, 0, 1) assert np.array_equal(observed, np.uint32([1])) def test_values_hit_upper_bound_negative_lower_bound_uint32(self): arr = np.uint32([1]) observed = iadt.clip_(arr, -1, 1) assert np.array_equal(observed, np.uint32([1])) def test_values_exceed_upper_bound_negative_lower_bound_uint32(self): arr = np.uint32([10]) observed = iadt.clip_(arr, -1, 1) assert np.array_equal(observed, np.uint32([1])) def test_values_hit_upper_bound_int8(self): arr = np.int8([127]) observed = iadt.clip_(arr, 0, 127) assert np.array_equal(observed, np.int8([127])) def test_values_within_bounds_upper_bound_is_dtype_limit_int8(self): arr = np.int8([127]) observed = iadt.clip_(arr, 0, 128) assert np.array_equal(observed, np.int8([127])) def test_values_hit_upper_bound_negative_lower_bound_int8(self): arr = np.int8([127]) observed = iadt.clip_(arr, -1, 127) assert np.array_equal(observed, np.int8([127])) def test_both_bounds_are_none_int8(self): arr = np.int8([1]) observed = iadt.clip_(arr, None, None) assert np.array_equal(observed, np.int8([1])) def test_lower_bound_is_none_int8(self): arr = np.int8([1]) observed = iadt.clip_(arr, None, 10) assert np.array_equal(observed, np.int8([1])) def test_upper_bound_is_none_int8(self): arr = np.int8([1]) observed = iadt.clip_(arr, -10, None) assert np.array_equal(observed, np.int8([1])) def test_values_exceed_upper_bound_and_lower_bound_is_none_int8(self): arr = np.int8([10]) observed = iadt.clip_(arr, None, 1) assert np.array_equal(observed, np.int8([1])) def test_values_exceed_lower_bound_and_upper_bound_is_none_int8(self): arr = np.int8([-10]) observed = iadt.clip_(arr, -1, None) assert np.array_equal(observed, np.int8([-1])) def test_numpy_scalar_hits_lower_bound_int8(self): # single value arrays, shape == tuple() arr = np.int8(-10) observed = iadt.clip_(arr, -10, 10) assert np.array_equal(observed, np.int8(-10)) def test_numpy_scalar_exceeds_lower_bound_int8(self): arr = np.int8(-10) observed = iadt.clip_(arr, -1, 10) assert np.array_equal(observed, np.int8(-1)) def test_numpy_scalar_exceeds_upper_bound_int8(self): arr = np.int8(10) observed = iadt.clip_(arr, -10, 1) assert np.array_equal(observed, np.int8(1)) class Test_clip_to_dtype_value_range(unittest.TestCase): def test_clip_to_wider_dtype(self): arr = np.array([-10, -1, 0, 1, 10, 255, 256], dtype=np.int16) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int32, validate=False) assert np.array_equal(arr_clipped, arr) assert arr_clipped.dtype.name == "int16" def test_clip_to_wider_dtype_given_by_name(self): arr = np.array([-10, -1, 0, 1, 10, 255, 256], dtype=np.int16) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), "int32", validate=False) assert np.array_equal(arr_clipped, arr) assert arr_clipped.dtype.name == "int16" def test_clip_to_wider_dtype_different_kind(self): arr = np.array([-10, -1, 0, 1, 10, 255, 256], dtype=np.int16) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), np.float64, validate=False) assert np.array_equal(arr_clipped, arr) assert arr_clipped.dtype.name == "int16" def test_clip_to_same_dtype(self): arr = np.array([-10, -1, 0, 1, 10, 255, 256], dtype=np.int16) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int16, validate=False) assert np.array_equal(arr_clipped, arr) assert arr_clipped.dtype.name == "int16" def test_clip_to_narrower_dtype(self): arr = np.array([-10, -1, 0, 1, 10, 255, 256], dtype=np.int16) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=False) expected = np.array([-10, -1, 0, 1, 10, 127, 127], dtype=np.int16) assert np.array_equal(arr_clipped, expected) assert arr_clipped.dtype.name == "int16" def test_dtype_is_array(self): arr = np.array([-10, -1, 0, 1, 10, 255, 256], dtype=np.int16) dt_arr = np.array([1], dtype=np.int32) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), dt_arr, validate=False) assert np.array_equal(arr_clipped, arr) assert arr_clipped.dtype.name == "int16" def test_validate_true_all_values_within_value_range(self): arr = np.array([-10, -1, 0, 1, 10, 126, 127], dtype=np.int16) arr_clipped = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=True) assert np.array_equal(arr_clipped, arr) assert arr_clipped.dtype.name == "int16" def test_validate_true_min_value_outside_value_range(self): arr = np.array([-200, -1, 0, 1, 10, 126, 127], dtype=np.int16) with self.assertRaises(AssertionError) as context: _ = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=True) assert ( "Minimum value of array is outside of allowed value range " "(-200.0000 vs -128.0000 to 127.0000)." in str(context.exception)) def test_validate_true_max_value_outside_value_range(self): arr = np.array([-10, -1, 0, 1, 10, 126, 200], dtype=np.int16) with self.assertRaises(AssertionError) as context: _ = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=True) assert ( "Maximum value of array is outside of allowed value range " "(200.0000 vs -128.0000 to 127.0000)." in str(context.exception)) def test_validate_too_few_values(self): arr = np.array([-10, 0, 200], dtype=np.int16) _ = iadt.clip_to_dtype_value_range_(np.copy(arr), np.int8, validate=2) def test_validate_enough_values(self): arr = np.array([-10, 0, 200], dtype=np.int16) with self.assertRaises(AssertionError) as context: _ = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=3) assert ( "Maximum value of array is outside of allowed value range " "(200.0000 vs -128.0000 to 127.0000)." in str(context.exception)) def test_validate_too_many_values(self): arr = np.array([-10, 0, 200], dtype=np.int16) with self.assertRaises(AssertionError) as context: _ = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=100) assert ( "Maximum value of array is outside of allowed value range " "(200.0000 vs -128.0000 to 127.0000)." in str(context.exception)) def test_validate_values_set(self): arr = np.array([-10, -1, 0, 1, 10, 126, 200], dtype=np.int16) with self.assertRaises(AssertionError) as context: _ = iadt.clip_to_dtype_value_range_( np.copy(arr), np.int8, validate=True, validate_values=(-5, 201)) assert ( "Maximum value of array is outside of allowed value range " "(201.0000 vs -128.0000 to 127.0000)." in str(context.exception)) class Test_gate_dtypes_strs(unittest.TestCase): def test_standard_scenario_all_allowed(self): for _ in range(3): dtypes = {np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = "uint8 float32 int64" disallowed = "bool" iadt.gate_dtypes_strs(dtypes, allowed, disallowed) def test_standard_scenario_one_disallowed(self): for _ in range(3): dtypes = {np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = "uint8 float32" disallowed = "bool int64" with self.assertRaises(ValueError) as context: iadt.gate_dtypes_strs(dtypes, allowed, disallowed) assert "Got dtype 'int64'" in str(context.exception) def test_empty_set_as_dtypes(self): for _ in range(3): dtypes = set() allowed = "uint8 float32 int64" disallowed = "bool" iadt.gate_dtypes_strs(dtypes, allowed, disallowed) def test_allowed_dtype_does_not_exist(self): dtypes = {np.dtype("uint8")} with self.assertRaises(KeyError): iadt.gate_dtypes_strs(dtypes, "uint8 int1000", "int8") def test_disallowed_dtype_does_not_exist(self): dtypes = {np.dtype("uint8")} with self.assertRaises(KeyError): iadt.gate_dtypes_strs(dtypes, "uint8", "int8 int1000") def test_overlap_between_allowed_and_disallowed(self): dtypes = {np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = "uint8 float32 int64" disallowed = "uint8 bool" with self.assertRaises(AssertionError) as context: iadt.gate_dtypes_strs(dtypes, allowed, disallowed) assert ( "Expected 'allowed' and 'disallowed' dtypes to not contain " "the same dtypes" in str(context.exception) ) def test_single_array_allowed(self): arr = np.zeros((1, 1, 3), dtype=np.int8) iadt.gate_dtypes_strs(arr, "int8", "") def test_single_array_disallowed(self): arr = np.zeros((1, 1, 3), dtype=np.int8) with self.assertRaises(ValueError) as context: iadt.gate_dtypes_strs(arr, "uint8", "int8") assert "Got dtype 'int8'" in str(context.exception) def test_list_of_single_array(self): arr = np.zeros((1, 1, 3), dtype=np.int8) iadt.gate_dtypes_strs([arr], "int8", "") def test_list_of_two_arrays_same_dtypes(self): arrays = [ np.zeros((1, 1, 3), dtype=np.int8), np.zeros((1, 1, 3), dtype=np.int8) ] iadt.gate_dtypes_strs(arrays, "int8", "") def test_list_of_two_arrays_different_dtypes(self): arrays = [ np.zeros((1, 1, 3), dtype=np.int8), np.zeros((1, 1, 3), dtype=np.uint8) ] iadt.gate_dtypes_strs(arrays, "int8 uint8", "") def test_list_of_two_arrays_same_dtypes_one_disallowed(self): arrays = [ np.zeros((1, 1, 3), dtype=np.int8), np.zeros((1, 1, 3), dtype=np.uint8) ] with self.assertRaises(ValueError) as context: iadt.gate_dtypes_strs(arrays, "int8", "uint8") assert "Got dtype 'uint8', which" in str(context.exception) class Test_gate_dtypes(unittest.TestCase): @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_standard_scenario_all_allowed(self): dtypes = [np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] allowed = [np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] disallowed = [np.dtype("bool")] iadt.gate_dtypes(dtypes, allowed, disallowed) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_standard_scenario_one_disallowed(self): dtypes = [np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] allowed = [np.dtype("uint8"), np.dtype("float32")] disallowed = [np.dtype("bool"), np.dtype("int64")] with self.assertRaises(ValueError) as context: iadt.gate_dtypes(dtypes, allowed, disallowed) assert "Got dtype 'int64'" in str(context.exception) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_standard_scenario_all_allowed_dtype_names(self): dtypes = [np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] allowed = ["uint8", "float32", "int64"] disallowed = ["bool"] iadt.gate_dtypes(dtypes, allowed, disallowed) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_standard_scenario_one_disallowed_dtype_names(self): dtypes = [np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] allowed = ["uint8", "float32"] disallowed = ["bool", "int64"] with self.assertRaises(ValueError) as context: iadt.gate_dtypes(dtypes, allowed, disallowed) assert "Got dtype 'int64'" in str(context.exception) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_standard_scenario_all_allowed_dtype_functions(self): dtypes = [np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] allowed = [np.uint8, np.float32, np.int64] disallowed = [np.bool_] iadt.gate_dtypes(dtypes, allowed, disallowed) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_standard_scenario_one_disallowed_dtype_functions(self): dtypes = [np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")] allowed = [np.uint8, np.float32] disallowed = [np.bool_, np.int64] with self.assertRaises(ValueError) as context: iadt.gate_dtypes(dtypes, allowed, disallowed) assert "Got dtype 'int64'" in str(context.exception) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_single_array_allowed(self): arr = np.zeros((1, 1, 3), dtype=np.int8) iadt.gate_dtypes(arr, ["int8"], []) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_single_array_disallowed(self): arr = np.zeros((1, 1, 3), dtype=np.int8) with self.assertRaises(ValueError) as context: iadt.gate_dtypes(arr, ["uint8"], ["int8"]) assert "Got dtype 'int8'" in str(context.exception) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_list_of_single_array(self): arr = np.zeros((1, 1, 3), dtype=np.int8) iadt.gate_dtypes([arr], [np.dtype("int8")], []) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_list_of_two_arrays_same_dtypes(self): arrays = [ np.zeros((1, 1, 3), dtype=np.int8), np.zeros((1, 1, 3), dtype=np.int8) ] iadt.gate_dtypes(arrays, [np.dtype("int8")], []) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_list_of_two_arrays_different_dtypes(self): arrays = [ np.zeros((1, 1, 3), dtype=np.int8), np.zeros((1, 1, 3), dtype=np.uint8) ] iadt.gate_dtypes(arrays, ["int8", "uint8"], []) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_list_of_two_arrays_same_dtypes_one_disallowed(self): arrays = [ np.zeros((1, 1, 3), dtype=np.int8), np.zeros((1, 1, 3), dtype=np.uint8) ] with self.assertRaises(ValueError) as context: iadt.gate_dtypes(arrays, "int8", "uint8") assert "Got dtype 'uint8', which" in str(context.exception) @ensure_deprecation_warning("imgaug.dtypes.gate_dtypes_strs") def test_single_dtype_function(self): dtype = np.int8 iadt.gate_dtypes(dtype, ["int8"], []) class Test__gate_dtypes(unittest.TestCase): def test_standard_scenario_all_allowed(self): dtypes = {np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = {np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} disallowed = {np.dtype("bool")} iadt._gate_dtypes(dtypes, allowed, disallowed) def test_standard_scenario_one_disallowed(self): dtypes = {np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = {np.dtype("uint8"), np.dtype("float32")} disallowed = {np.dtype("bool"), np.dtype("int64")} with self.assertRaises(ValueError) as context: iadt._gate_dtypes(dtypes, allowed, disallowed) assert "Got dtype 'int64'" in str(context.exception) def test_all_allowed_input_is_list_of_dtypes(self): dtypes = {np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = {np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} disallowed = {np.dtype("bool")} iadt._gate_dtypes(dtypes, allowed, disallowed) def test_all_allowed_input_is_list_of_dtype_functions(self): dtypes = {np.dtype("uint8"), np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} allowed = {np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} disallowed = {np.dtype("bool")} iadt._gate_dtypes(dtypes, allowed, disallowed) def test_empty_set_as_dtypes(self): dtypes = set() allowed = {np.dtype("uint8"), np.dtype("float32"), np.dtype("int64")} disallowed = {np.dtype("bool")} iadt._gate_dtypes(dtypes, allowed, disallowed) def test_single_dtype_allowed(self): dtype = np.dtype("int8") iadt._gate_dtypes({dtype}, {np.dtype("int8")}, None) def test_single_dtype_disallowed(self): dtype = np.dtype("int8") with self.assertRaises(ValueError) as context: iadt._gate_dtypes({dtype}, {np.dtype("uint8")}, {np.dtype("int8")}) assert "Got dtype 'int8', which" in str(context.exception) def test_single_dtype_disallowed_augmenter_set(self): class _DummyAugmenter(object): def __init__(self): self.name = "foo" dtype = np.dtype("int8") dummy_augmenter = _DummyAugmenter() with self.assertRaises(ValueError) as context: iadt._gate_dtypes( {dtype}, {np.dtype("uint8")}, {np.dtype("int8")}, augmenter=dummy_augmenter ) assert "Got dtype 'int8' in augmenter 'foo'" in str(context.exception) def test_list_of_two_dtypes_both_same(self): dtypes = { np.dtype("int8"), np.dtype("int8") } iadt._gate_dtypes(dtypes, {np.dtype("int8")}, None) def test_list_of_two_dtypes_both_different(self): dtypes = { np.dtype("int8"), np.dtype("uint8") } iadt._gate_dtypes(dtypes, {np.dtype("int8"), np.dtype("uint8")}, None) def test_list_of_two_dtypes_both_different_one_disallowed(self): dtypes = { np.dtype("int8"), np.dtype("uint8") } with self.assertRaises(ValueError) as context: iadt._gate_dtypes(dtypes, {np.dtype("int8")}, {np.dtype("uint8")}) assert "Got dtype 'uint8', which" in str(context.exception) def test_dtype_not_in_allowed_or_disallowed(self): dtypes = { np.dtype("int8"), np.dtype("float32") } with warnings.catch_warnings(record=True) as caught_warnings: warnings.simplefilter("always") iadt._gate_dtypes(dtypes, {np.dtype("int8")}, {np.dtype("uint8")}) assert len(caught_warnings) == 1 assert ( "Got dtype 'float32', which" in str(caught_warnings[-1].message)) def test_dtype_not_in_allowed_or_disallowed_augmenter_set(self): class _DummyAugmenter(object): def __init__(self): self.name = "foo" dtypes = { np.dtype("int8"), np.dtype("float32") } dummy_augmenter = _DummyAugmenter() with warnings.catch_warnings(record=True) as caught_warnings: warnings.simplefilter("always") iadt._gate_dtypes( dtypes, {np.dtype("int8")}, {np.dtype("uint8")}, augmenter=dummy_augmenter ) assert len(caught_warnings) == 1 assert ( "Got dtype 'float32' in augmenter 'foo'" in str(caught_warnings[-1].message))