def test_bounds(self):
        """
        Make sure error is thrown when trying to access out of bounds

        """
        original = np.arange(5**4).reshape(tuple([5] * 4))
        global_offset = (100, 200, 300, 400)
        offset_array = GlobalOffsetArray(original)

        with self.assertRaises(IndexError):
            offset_array[5:6, 4:5, 6:7, 7:8]

        with self.assertRaises(IndexError):
            offset_array[2, 2:5, 6:8, 0:2]

        with self.assertRaises(IndexError):
            offset_array[2, 9, 0:3, 0:2]

        offset_array = GlobalOffsetArray(original, global_offset=global_offset)

        with self.assertRaises(IndexError):
            offset_array[105:106, 204:205, 306:307, 407:408]

        with self.assertRaises(IndexError):
            offset_array[102, 202:205, 306:308, 400:402]

        with self.assertRaises(IndexError):
            offset_array[102, 209, 300:303, 400:402]
    def test_subarray(self):
        """
        Make sure subarrays of contain the correct adjusted global_offset and a copy is returned

        """
        original = np.arange(5**4).reshape(tuple([5] * 4))
        global_offset = (100, 200, 300, 400)
        offset_array = GlobalOffsetArray(original, global_offset=global_offset)

        # test slice with only slices
        offset_index = (slice(100, 102), slice(202, 205), slice(303, 305),
                        slice(400, 403))
        sub_array = offset_array[offset_index]
        self.assertTrue(np.array_equal(original[0:2, 2:5, 3:5, 0:3],
                                       sub_array))
        self.assertEqual((100, 202, 303, 400), sub_array.global_offset)
        self.assertTrue(
            np.array_equal(offset_array[offset_index],
                           sub_array[offset_index]))

        # ensure that returned sub_array is actually a view
        sub_array[sub_array.global_offset] = 1337
        self.assertEqual(1337, offset_array[sub_array.global_offset])

        # test slice with some slices some fixed
        offset_index = (slice(100, 102), 203, slice(303, 305), slice(400, 403))
        sub_array = offset_array[offset_index]
        self.assertTrue(np.array_equal(original[0:2, 3, 3:5, 0:3], sub_array))
        self.assertEqual((100, 303, 400), sub_array.global_offset)
        self.assertTrue(
            np.array_equal(
                offset_array[offset_index],
                sub_array[tuple(s for s in offset_index
                                if isinstance(s, slice))]))
    def test_get_with_offset(self):
        """
        Make sure all global_offset_arrays are equivalent when given offset the proper offset indices.
        """
        for test_array in TEST_ARRAYS:
            # set offset at each dimension to the dimension index + 1
            offset = tuple(
                [index + 1 for index in range(0, len(test_array.shape))])
            shape = test_array.shape
            offset_array = GlobalOffsetArray(test_array, global_offset=offset)
            self.assertEqual(offset, offset_array.global_offset)

            test_slices = tuple(
                slice(0, shape[dimension])
                for dimension in range(0, test_array.ndim))
            # same as test_slices but at offset
            offset_slices = tuple(
                slice(test_slice.start + offset[dimension], test_slice.stop +
                      offset[dimension])
                for dimension, test_slice in enumerate(test_slices))
            sliced_offset_array = offset_array[offset_slices]
            self.assertTrue(
                np.array_equal(test_array[test_slices], sliced_offset_array))
            self.recurse_compare(test_array[test_slices], sliced_offset_array,
                                 test_array.shape)
 def test_get_no_offset(self):
     """
     Make sure all arrays are properly equivalent when no offset is given
     """
     for test_array in TEST_ARRAYS:
         offset_array = GlobalOffsetArray(test_array)
         self.assertEqual(tuple([0] * test_array.ndim),
                          offset_array.global_offset)
         self.assertTrue(np.array_equal(test_array, offset_array))
 def test_get_offset_origin(self):
     """
     Make sure all arrays are properly equivalent when offset of the origin is given
     """
     for test_array in TEST_ARRAYS:
         offset_array = GlobalOffsetArray(
             test_array,
             global_offset=tuple(0 for _ in range(0, test_array.ndim)))
         self.assertEqual(tuple([0] * test_array.ndim),
                          offset_array.global_offset)
         self.assertTrue(np.array_equal(test_array, offset_array))
         self.recurse_compare(test_array, offset_array, test_array.shape)
    def generate_data(self, ndim, length):
        """
        Generate test data
        """
        original = np.arange(1,
                             length**ndim + 1).reshape(tuple([length] * ndim))
        copy = original.copy()

        global_offset = tuple(dimension * 100
                              for dimension in range(1, ndim + 1))
        offset_array = GlobalOffsetArray(original, global_offset=global_offset)

        return (copy, offset_array)
    def generate_replacement(self, ndim, length, global_offset):
        """
        """
        # Test with regulard ndarray are properly set into the offset_array
        replacement_length = floor(length / 2)
        replacement = np.arange(1, replacement_length**ndim + 1).reshape(
            tuple([replacement_length] * ndim))

        # replace global offset array with new replaced value
        replacement_slice = ()
        offset_replace_slice = ()
        replacement_offset = ()
        for offset in global_offset:
            replacement_slice += (slice(replacement_length,
                                        replacement_length * 2), )
            offset_replace_slice += (slice(replacement_length + offset,
                                           replacement_length * 2 + offset), )
            replacement_offset += (replacement_length + offset, )

        replacement = GlobalOffsetArray(replacement,
                                        global_offset=replacement_offset)

        return (replacement_slice, offset_replace_slice, replacement)
    def test_operator_diff_size_global_offset_array(self):
        """
        Test to make sure operators return a copy of the original array
        """
        ndim = 5
        length = 4

        for op in STANDARD_OPERATORS | IN_PLACE_OPERATORS:
            for forward in [True, False]:
                (original, offset_array) = self.generate_data(ndim, length)
                half_size = tuple(
                    floor(size / 2) for size in offset_array.shape)
                offset = tuple(half_size[dimension] + offset for dimension,
                               offset in enumerate(offset_array.global_offset))
                half_slice = tuple(slice(s, s + s) for s in half_size)
                operate_param = GlobalOffsetArray(
                    np.ones(half_size, dtype=offset_array.dtype) * 255,
                    global_offset=offset)
                # itrue div requires floats when doing true division (can't do in place conversion to float)
                if op == operator.itruediv:
                    original = original.astype(np.float64)
                    offset_array = offset_array.astype(np.float64)
                    operate_param = operate_param.astype(np.float64)

                if forward:
                    left_expected = original[half_slice]
                    right_expected = operate_param.view(np.ndarray)
                    left_offset = offset_array
                    right_offset = operate_param
                else:
                    # test operation commutativity
                    left_expected = operate_param.view(np.ndarray)
                    right_expected = original[half_slice]
                    left_offset = operate_param
                    right_offset = offset_array

                    # in place operators should only work if the left param is larger than the right
                    if op in IN_PLACE_OPERATORS:
                        with self.assertRaises(ValueError):
                            op(left_offset, right_offset)
                        continue

                actual_result = op(left_offset, right_offset)

                expected_sub_array = op(left_expected, right_expected)
                if op in STANDARD_OPERATORS:
                    expected = original.astype(type(
                        expected_sub_array.item(0)))
                    actual = actual_result
                else:
                    # in place operations modify originals
                    expected = original
                    actual = offset_array

                # Simulate expected
                expected[half_slice] = expected_sub_array

                # ensure global_offset is preserved
                self.assertEqual(offset_array.global_offset,
                                 actual.global_offset)

                self.assertTrue(np.array_equal(expected, actual))

                # ensure the results that are returned are a copy of an array instead of a view just like ndarray
                expected[tuple([0] * ndim)] = 1337
                actual[actual.global_offset] = 1337

                # original arrays were not modified
                self.assertEqual(np.any(original == 1337),
                                 np.any(offset_array == 1337))

                # Fail on partial overlap
                with self.assertRaises(ValueError):
                    operate_param.global_offset = tuple(
                        floor(size / 2) + floor(size / 4)
                        for size in offset_array.shape)
                    op(left_offset, right_offset)
    def test_operator_same_size_global_offset_array(self):
        """
        Test that when using operators on two GlobalOffsetArray it works only when they have the same global_offset
        """
        ndim = 5
        length = 4

        for op in STANDARD_OPERATORS | IN_PLACE_OPERATORS:
            for forward in [True, False]:
                (original, offset_array) = self.generate_data(ndim, length)
                operate_param = GlobalOffsetArray(
                    np.ones(offset_array.shape, dtype=offset_array.dtype) * 10,
                    global_offset=offset_array.global_offset)
                # itrue div requires floats when doing true division (can't do in place conversion to float)
                if op == operator.itruediv:
                    original = original.astype(np.float64)
                    offset_array = offset_array.astype(np.float64)
                    operate_param = operate_param.astype(np.float64)

                # Make sure to compare expected results as a ndarray because operate_param is a GlobalOffsetArray.
                if forward:
                    left_expected = original.view(np.ndarray)
                    right_expected = operate_param.view(np.ndarray)
                    left_offset = offset_array
                    right_offset = operate_param
                else:
                    # test operation commutativity
                    left_expected = operate_param.view(np.ndarray)
                    right_expected = original.view(np.ndarray)
                    left_offset = operate_param
                    right_offset = offset_array

                expected_result = op(left_expected, right_expected)
                actual_result = op(left_offset, right_offset)

                if op in STANDARD_OPERATORS:
                    expected = expected_result
                    actual = actual_result
                else:
                    expected = original
                    actual = offset_array

                # ensure global_offset is preserved
                self.assertEqual(offset_array.global_offset,
                                 actual.global_offset)

                # ensure actual results match that of a regular ndarray
                self.assertTrue(np.array_equal(expected, actual))

                # ensure the results that are returned are a copy of an array instead of a view just like ndarray
                expected[tuple([0] * ndim)] = 1337
                actual[actual.global_offset] = 1337

                # original arrays were not modified
                self.assertEqual(np.any(original == 1337),
                                 np.any(offset_array == 1337))

                # Try testing with the operate param with a different global_offset
                operate_param.global_offset = tuple([1337] * ndim)
                with self.assertRaises(ValueError):
                    op(left_offset, right_offset)

                # Try testing with the operate param with a partially overlapping data
                operate_param.global_offset = tuple(
                    floor(size / 2) + offset for size, offset in zip(
                        offset_array.shape, offset_array.global_offset))
                with self.assertRaises(ValueError):
                    op(left_offset, right_offset)