Ejemplo n.º 1
0
def test_bbox_hypervolume_other() -> None:
    """
    Test that we get the expected non-trivial area for bboxes of various
    dimensions.
    """
    # 1D
    minp = [4]
    maxp = [8]
    expected_area = 4
    assert AxisAlignedBoundingBox(minp, maxp).hypervolume == expected_area

    # 2D
    minp = [0, 4]
    maxp = [2, 10]
    expected_area = 12  # 2 * 6
    assert AxisAlignedBoundingBox(minp, maxp).hypervolume == expected_area

    # 3D
    minp = [0, 4, 3]
    maxp = [1, 10, 8]
    expected_area = 30  # 1 * 6 * 5
    assert AxisAlignedBoundingBox(minp, maxp).hypervolume == expected_area

    # 4D
    minp = [0, 4, 3, 5]
    maxp = [1, 10, 8, 9]
    expected_area = 120  # 1 * 6 * 5 * 4
    assert AxisAlignedBoundingBox(minp, maxp).hypervolume == expected_area
Ejemplo n.º 2
0
def test_bbox_construction_incongruous_shape() -> None:
    """
    Test that construction fails when one or both input coordinates are not a
    single array dimension (i.e. multi-dimensional shape in numpy.array
    parlance).
    """
    minp_1dim = (0, )
    minp_2dim = ((0, ), (1, ))

    maxp_1dim = (1, )
    maxp_2dim = ((1, ), (2, ))

    with pytest.raises(ValueError,
                       match=r"One or both vertices provided had "
                       r"more than one array dimension "
                       r"\(min_vertex\.ndim == 2, "
                       r"max_vertex\.ndim == 1\)\."):
        # noinspection PyTypeChecker
        AxisAlignedBoundingBox(minp_2dim, maxp_1dim)  # type: ignore
    with pytest.raises(ValueError,
                       match=r"One or both vertices provided had "
                       r"more than one array dimension "
                       r"\(min_vertex\.ndim == 1, "
                       r"max_vertex\.ndim == 2\)\."):
        # noinspection PyTypeChecker
        AxisAlignedBoundingBox(minp_1dim, maxp_2dim)  # type: ignore
    with pytest.raises(ValueError,
                       match=r"One or both vertices provided had "
                       r"more than one array dimension "
                       r"\(min_vertex\.ndim == 2, "
                       r"max_vertex\.ndim == 2\)\."):
        # noinspection PyTypeChecker
        AxisAlignedBoundingBox(minp_2dim, maxp_2dim)  # type: ignore
Ejemplo n.º 3
0
def test_bbox_equality_other_not_close() -> None:
    """
    Test that other bbox is not equal when bbox is sufficiently different.
    """
    bb1 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])
    # Differs in max z bounds.
    bb2 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 5])
    assert not (bb1 == bb2)
Ejemplo n.º 4
0
def test_bbox_equality_other_is_copy() -> None:
    """
    Test that a bounding box is equal to an equivalent other bounding box
    instance.
    """
    bb1 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])
    bb2 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])
    assert bb1 == bb2
Ejemplo n.º 5
0
def test_getstate_format() -> None:
    """
    Test expected __getstate__ format.
    """
    min_v = (4.2, 8.9, 1)
    max_v = (9.2, 9.0, 48)
    expected_state = ([4.2, 8.9, 1], [9.2, 9.0, 48])

    bb1 = AxisAlignedBoundingBox(min_v, max_v)
    assert bb1.__getstate__() == expected_state
Ejemplo n.º 6
0
def test_setstate_format() -> None:
    """
    Test expected state format compatible with setstate
    """
    state = ([4.2, 8.9, 1], [9.2, 9.0, 48])
    expected_min_v = (4.2, 8.9, 1)
    expected_max_v = (9.2, 9.0, 48)

    bb = AxisAlignedBoundingBox([0], [1])
    bb.__setstate__(state)
    numpy.testing.assert_allclose(bb.min_vertex, expected_min_v)
    numpy.testing.assert_allclose(bb.max_vertex, expected_max_v)
Ejemplo n.º 7
0
 def test_in_bounds_zero_crop_area(self) -> None:
     """
     Test that crop is not ``in_bounds`` when it has zero area (undefined).
     """
     # noinspection PyArgumentList
     bb = AxisAlignedBoundingBox([1, 2], [1, 2])
     assert not crop_in_bounds(bb, 4, 6)
Ejemplo n.º 8
0
    def test_in_bounds_completely_outside(self) -> None:
        """
        Test that being completely outside the given bounds causes
        ``in_bounds`` to return False.
        """
        bb = AxisAlignedBoundingBox([100, 100], [102, 102])
        assert not crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([-100, -100], [-98, -98])
        assert not crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([-100, 100], [-98, 102])
        assert not crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([100, -100], [102, -98])
        assert not crop_in_bounds(bb, 4, 6)
Ejemplo n.º 9
0
def test_bbox_not_equal(m_bbox_eq: mock.MagicMock) -> None:
    """
    Test that non-equality is just calling the __eq__ in
    AxisAlignedBoundingBox.

    :param mock.MagicMock m_bbox_eq:
    """
    bb1 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])
    bb2 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])

    m_bbox_eq.assert_not_called()

    # noinspection PyStatementEffect
    bb1 != bb2

    m_bbox_eq.assert_called_once_with(bb2)
Ejemplo n.º 10
0
def test_bbox_repr() -> None:
    """
    Test that __repr__ returns without error.
    """
    assert repr(AxisAlignedBoundingBox([0], [1.2])) == \
        "<smqtk_image_io.bbox.AxisAlignedBoundingBox " \
        "min_vertex=[0] max_vertex=[1.2]>"
Ejemplo n.º 11
0
def test_bbox_set_vertices_maintain_type_float() -> None:
    """
    Test that ndarray dtypes inherit from input float values explicitly.
    """
    # Float input coordinates (1d)
    minv = [0.]
    maxv = [1.]

    # Mock instance so as to not actually hit __init__ method.
    m_bb = mock.MagicMock(spec_set=AxisAlignedBoundingBox)
    # Invoke private method, which should set attributes onto `m_bb`.
    AxisAlignedBoundingBox._set_vertices(m_bb, minv, maxv)

    # BOTH vertices should be integer since input coordinates are integers.
    assert issubclass(m_bb.min_vertex.dtype.type, numpy.float64)
    assert issubclass(m_bb.max_vertex.dtype.type, numpy.float64)
Ejemplo n.º 12
0
    def test_in_bounds_inside_edges(self) -> None:
        """
        Test that a crop is "in bounds" when contacting the 4 edges of the
        given rectangular bounds.

            +--+
            |  |
            ## |  => (4, 6) image, (2,2) crop
            ## |
            |  |
            +--+

            +##+
            |##|
            |  |  => (4, 6) image, (2,2) crop
            |  |
            |  |
            +--+

            +--+
            |  |
            | ##  => (4, 6) image, (2,2) crop
            | ##
            |  |
            +--+

            +--+
            |  |
            |  |  => (4, 6) image, (2,2) crop
            |  |
            |##|
            +##+

        """
        # noinspection PyArgumentList
        bb = AxisAlignedBoundingBox([0, 2], [2, 4])
        assert crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([1, 0], [3, 2])
        assert crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([2, 2], [4, 4])
        assert crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([1, 4], [3, 6])
        assert crop_in_bounds(bb, 4, 6)
Ejemplo n.º 13
0
def test_bbox_equality_other_is_close() -> None:
    """
    Test that a bounding box is equal to an equivalent other bounding box
    instance.
    """
    e = 1e-8  # default absolute tolerance on ``numpy.allclose`` function.
    bb1 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])
    bb2 = AxisAlignedBoundingBox([1 + e, 2 + e, 3 + e], [2 + e, 3 + e, 4 + e])

    # Basic array equality is exact, which should show that these are not
    # strictly equal.
    # noinspection PyUnresolvedReferences
    assert (bb1.min_vertex != bb2.min_vertex).all()
    # noinspection PyUnresolvedReferences
    assert (bb1.max_vertex != bb2.max_vertex).all()

    assert bb1 == bb2
Ejemplo n.º 14
0
def test_bbox_hash() -> None:
    """
    Test expected hashing of bounding box.
    """
    p1 = (0, 1, 2)
    p2 = (1, 2, 3)
    expected_hash = hash((p1, p2))
    assert hash(AxisAlignedBoundingBox(p1, p2)) == expected_hash
Ejemplo n.º 15
0
    def test_in_bounds_crossing_edges(self) -> None:
        """
        Test that ``in_bounds`` returns False when crop crossed the 4 edges.

            +--+
            |  |
           ### |  => (4, 6) image, (3,2) crop
           ### |
            |  |
            +--+

            +--+
            |  |
            | ###  => (4, 6) image, (3,2) crop
            | ###
            |  |
            +--+

             ##
            +##+
            |##|
            |  |  => (4, 6) image, (2,3) crop
            |  |
            |  |
            +--+

            +--+
            |  |
            |  |  => (4, 6) image, (2,3) crop
            |  |
            |##|
            +##+
             ##

        """
        bb = AxisAlignedBoundingBox([-1, 2], [2, 4])
        assert not crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([2, 2], [5, 4])
        assert not crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([1, -1], [3, 2])
        assert not crop_in_bounds(bb, 4, 6)

        bb = AxisAlignedBoundingBox([1, 4], [3, 7])
        assert not crop_in_bounds(bb, 4, 6)
Ejemplo n.º 16
0
def test_bbox_hypervolume_1(ndim: int) -> None:
    """
    Test that we get the expected 1-area from various 1-area hyper-cubes.
    """
    minp = [0] * ndim
    maxp = [1] * ndim
    expected_area = 1
    assert AxisAlignedBoundingBox(minp, maxp).hypervolume == expected_area
Ejemplo n.º 17
0
def test_bbox_dtype() -> None:
    """
    Test getting the representative dtype of the bounding box, including mix
    vertex array types
    """
    # int
    bb = AxisAlignedBoundingBox([0], [1])
    assert issubclass(bb.dtype.type, numpy.signedinteger)
    bb = AxisAlignedBoundingBox(numpy.array([0], dtype=numpy.uint8),
                                numpy.array([1], dtype=numpy.uint8))
    assert issubclass(bb.dtype.type, numpy.uint8)
    bb = AxisAlignedBoundingBox(numpy.array([0], dtype=numpy.uint8),
                                numpy.array([1], dtype=numpy.uint32))
    assert issubclass(bb.dtype.type, numpy.uint32)

    # float
    bb = AxisAlignedBoundingBox([0.], [1.])
    assert issubclass(bb.dtype.type, numpy.float64)

    bb = AxisAlignedBoundingBox(numpy.array([0], dtype=numpy.float32),
                                numpy.array([1], dtype=numpy.float16))
    assert issubclass(bb.dtype.type, numpy.float32)

    # mixed
    bb = AxisAlignedBoundingBox([0], [1.0])
    assert issubclass(bb.dtype.type, numpy.float64)
    bb = AxisAlignedBoundingBox([0.0], [1])
    assert issubclass(bb.dtype.type, numpy.float64)
Ejemplo n.º 18
0
def test_bbox_set_vertices(ndim: int, seq_type: Any) -> None:
    """
    Test constructing an AxisAlignedBoundingBox with ``ndim`` coordinates.
    """
    minv = [random.randint(0, 9) for _ in range(ndim)]
    maxv = [random.randint(10, 19) for _ in range(ndim)]
    minv_s = seq_type(minv)
    maxv_s = seq_type(maxv)

    # Mock instance so as to not actually hit __init__ method.
    m_bb = mock.MagicMock(spec_set=AxisAlignedBoundingBox)
    # Invoke private method, which should set attributes onto `m_bb`.
    AxisAlignedBoundingBox._set_vertices(m_bb, minv_s, maxv_s)

    assert isinstance(m_bb.min_vertex, numpy.ndarray)
    assert isinstance(m_bb.max_vertex, numpy.ndarray)
    numpy.testing.assert_allclose(m_bb.min_vertex, minv)
    numpy.testing.assert_allclose(m_bb.max_vertex, maxv)
Ejemplo n.º 19
0
def test_bbox_deltas_4d() -> None:
    """
    Test that `deltas` property returns the correct value for an example 1D
    region.
    """
    minp = [3] * 4
    maxp = [9] * 4
    expected = [6] * 4
    numpy.testing.assert_allclose(
        AxisAlignedBoundingBox(minp, maxp).deltas, expected)
Ejemplo n.º 20
0
def test_bbox_construction_maxp_not_greater() -> None:
    """
    Test the check that the max-coordinate must be >= min-coordinate.
    """
    minp = (10, 10)
    maxp = (11, 9)
    with pytest.raises(ValueError,
                       match=r"The maximum vertex was not strictly >= the "
                       r"minimum vertex\."):
        AxisAlignedBoundingBox(minp, maxp)
Ejemplo n.º 21
0
def test_bbox_ndim(ndim: int) -> None:
    """
    Test that the ``ndim`` property correctly reflects the dimensionality of
    the coordinates stored.

    :param ndim: Dimension integer fixture result.

    """
    bb = AxisAlignedBoundingBox([1] * ndim, [2] * ndim)
    assert bb.ndim == ndim
Ejemplo n.º 22
0
def test_bbox_deltas_3d() -> None:
    """
    Test that `deltas` property returns the correct value for an example 1D
    region.
    """
    minp = [29, 38, 45]
    maxp = [792, 83, 45]
    expected = [763, 45, 0]
    numpy.testing.assert_allclose(
        AxisAlignedBoundingBox(minp, maxp).deltas, expected)
Ejemplo n.º 23
0
    def setUpClass(cls):
        cls.gh_image_fp = os.path.join(TEST_DATA_DIR, "grace_hopper.png")
        cls.gh_file_element = DataFileElement(cls.gh_image_fp)
        assert cls.gh_file_element.content_type() == 'image/png'

        cls.gh_cropped_image_fp = \
            os.path.join(TEST_DATA_DIR, 'grace_hopper.100x100+100+100.png')
        cls.gh_cropped_file_element = DataFileElement(cls.gh_cropped_image_fp)
        assert cls.gh_cropped_file_element.content_type() == 'image/png'
        cls.gh_cropped_bbox = AxisAlignedBoundingBox([100, 100], [200, 200])
Ejemplo n.º 24
0
    def test_load_as_matrix_with_crop_not_in_bounds(self):
        """
        Test that error is raised when crop bbox is not fully within the image
        bounds.
        """
        inst = PilImageReader()

        # Nowhere close
        bb = AxisAlignedBoundingBox([5000, 6000], [7000, 8000])
        with pytest.raises(RuntimeError,
                           match=r"Crop provided not within input image\. "
                           r"Image shape: \(512, 600\), crop: "):
            inst.load_as_matrix(self.gh_file_element, pixel_crop=bb)

        # Outside left side
        bb = AxisAlignedBoundingBox([-1, 1], [2, 2])
        with pytest.raises(RuntimeError,
                           match=r"Crop provided not within input image\. "
                           r"Image shape: \(512, 600\), crop: "):
            inst.load_as_matrix(self.gh_file_element, pixel_crop=bb)

        # Outside top side
        bb = AxisAlignedBoundingBox([1, -1], [2, 2])
        with pytest.raises(RuntimeError,
                           match=r"Crop provided not within input image\. "
                           r"Image shape: \(512, 600\), crop: "):
            inst.load_as_matrix(self.gh_file_element, pixel_crop=bb)

        # Outside right side
        bb = AxisAlignedBoundingBox([400, 400], [513, 600])
        with pytest.raises(RuntimeError,
                           match=r"Crop provided not within input image\. "
                           r"Image shape: \(512, 600\), crop: "):
            inst.load_as_matrix(self.gh_file_element, pixel_crop=bb)

        # Outside bottom side
        bb = AxisAlignedBoundingBox([400, 400], [512, 601])
        with pytest.raises(RuntimeError,
                           match=r"Crop provided not within input image\. "
                           r"Image shape: \(512, 600\), crop: "):
            inst.load_as_matrix(self.gh_file_element, pixel_crop=bb)
Ejemplo n.º 25
0
def test_bbox_set_vertices_maintain_type_mixed() -> None:
    """
    Test that ndarray dtypes inherit from mixed float and integer values
    explicitly.
    """
    # Mock instance so as to not actually hit __init__ method.
    m_bb = mock.MagicMock(spec_set=AxisAlignedBoundingBox)

    # Integer/Float coordinates (3d)
    minv = [0, 1, 2]  # integer
    maxv = [1, 2.0, 3]  # float
    AxisAlignedBoundingBox._set_vertices(m_bb, minv, maxv)
    assert issubclass(m_bb.min_vertex.dtype.type, numpy.integer)
    assert issubclass(m_bb.max_vertex.dtype.type, numpy.float64)

    # Float/Integer coordinates (3d)
    minv = [0, 1, 2.0]  # type: ignore  # float
    maxv = [1, 2, 3]  # type: ignore  # integer
    AxisAlignedBoundingBox._set_vertices(m_bb, minv, maxv)
    assert issubclass(m_bb.min_vertex.dtype.type, numpy.float64)
    assert issubclass(m_bb.max_vertex.dtype.type, numpy.integer)
Ejemplo n.º 26
0
def test_bbox_equality_other_not_close_enough(m_bbox_rtol: int,
                                              m_bbox_atol: int) -> None:
    """
    Test modifying tolerance values
    :return:
    """
    e = 1e-8  # default absolute tolerance on ``numpy.allclose`` function.
    bb1 = AxisAlignedBoundingBox([1, 2, 3], [2, 3, 4])
    bb2 = AxisAlignedBoundingBox([1 + e, 2 + e, 3 + e], [2 + e, 3 + e, 4 + e])

    # Basic array equality is exact, which should show that these are not
    # strictly equal.
    # noinspection PyUnresolvedReferences
    assert (bb1.min_vertex != bb2.min_vertex).all()
    # noinspection PyUnresolvedReferences
    assert (bb1.max_vertex != bb2.max_vertex).all()

    # If we reduce the tolerances, the 1e-8 difference will become intolerable.
    m_bbox_rtol.return_value = 1.e-10  # type: ignore
    m_bbox_atol.return_value = 1.e-16  # type: ignore
    assert not (bb1 == bb2)
Ejemplo n.º 27
0
    def test_load_as_matrix_with_crop_not_integer(self):
        """
        Test passing a bounding box that is not integer aligned, which should
        raise an error in the super call.
        """
        inst = PilImageReader()
        bb = AxisAlignedBoundingBox([100, 100.6], [200, 200.2])

        with pytest.raises(ValueError,
                           match=r"Crop bounding box must be "
                           r"composed of integer "
                           r"coordinates\."):
            inst.load_as_matrix(self.gh_file_element, pixel_crop=bb)
Ejemplo n.º 28
0
def test_serialize_deserialize_pickle() -> None:
    """
    Test expected state representation.
    """
    min_v = (4.2, 8.9, 1)
    max_v = (9.2, 9.0, 48)

    bb1 = AxisAlignedBoundingBox(min_v, max_v)
    #: :type: AxisAlignedBoundingBox
    bb2 = pickle.loads(pickle.dumps(bb1))

    numpy.testing.assert_allclose(bb2.min_vertex, min_v)
    numpy.testing.assert_allclose(bb2.max_vertex, max_v)
Ejemplo n.º 29
0
def test_load_as_matrix_crop_zero_volume() -> None:
    """
    Test that a ValueError is raised when a crop bbox is passed with zero
    volume.
    """
    m_reader = mock.MagicMock(spec=ImageReader)
    m_data = mock.MagicMock(spec_set=DataElement)

    crop_bb = AxisAlignedBoundingBox([0, 0], [0, 0])
    with pytest.raises(ValueError,
                       match=r"Volume of crop bounding box must be "
                       r"greater than 0\."):
        ImageReader.load_as_matrix(m_reader, m_data, pixel_crop=crop_bb)
Ejemplo n.º 30
0
    def setUpClass(cls) -> None:
        # Initialize test image paths/elements/associated crop boxes.

        cls.gh_image_fp = os.path.join(TEST_DATA_DIR, "grace_hopper.png")
        cls.gh_file_element = DataFileElement(cls.gh_image_fp, readonly=True)
        assert cls.gh_file_element.content_type() == 'image/png'

        cls.gh_cropped_image_fp = \
            os.path.join(TEST_DATA_DIR, 'grace_hopper.100x100+100+100.png')
        cls.gh_cropped_file_element = \
            DataFileElement(cls.gh_cropped_image_fp, readonly=True)
        assert cls.gh_cropped_file_element.content_type() == 'image/png'
        cls.gh_cropped_bbox = AxisAlignedBoundingBox([100, 100], [200, 200])