Example #1
0
 def test_load_as_matrix_channel_subselection(self):
     """
     Test correctly loading image with only specific channels of what is
     available.
     """
     # Load image normally, assumed functional (see above)
     mat_rgb = GdalImageReader().load_as_matrix(GH_FILE_ELEMENT)
     mat_gb = GdalImageReader(channel_order='gb')\
         .load_as_matrix(GH_FILE_ELEMENT)
     numpy.testing.assert_allclose(mat_gb, mat_rgb[:, :, [1, 2]])
Example #2
0
 def test_init_channel_order_not_sequence(self):
     """
     Test that ``channel_order`` sequence check catches appropriate culprits.
     """
     expected_message = 'Channel order must be a sequence'
     with pytest.raises(ValueError, match=expected_message):
         # Sets should be invalid.
         # noinspection PyTypeChecker
         GdalImageReader(channel_order={1, 2, 3})
     with pytest.raises(ValueError, match=expected_message):
         GdalImageReader(channel_order={1: 0, 2: 3})
Example #3
0
 def test_load_as_matrix_channel_subselection_cropped(self):
     """
     Same as previous test but with crop region provided.
     """
     # Load image normally, assumed functional (see above)
     mat_rgb = GdalImageReader().load_as_matrix(GH_CROPPED_FILE_ELEMENT)
     mat_gb = GdalImageReader(channel_order='gb') \
         .load_as_matrix(GH_FILE_ELEMENT, pixel_crop=GH_CROPPED_BBOX)
     assert mat_gb.ndim == 3
     assert mat_gb.shape == (100, 100, 2)
     numpy.testing.assert_allclose(mat_gb, mat_rgb[:, :, [1, 2]])
Example #4
0
 def test_init_channel_order_empty_sequence(self):
     """
     Test that we get an error if an empty sequence is provided.
     """
     expected_message = "Invalid channel order, must request at least "\
                        "one band"
     with pytest.raises(ValueError, match=expected_message):
         GdalImageReader(channel_order='')
     with pytest.raises(ValueError, match=expected_message):
         GdalImageReader(channel_order=[])
     with pytest.raises(ValueError, match=expected_message):
         GdalImageReader(channel_order=())
Example #5
0
 def test_load_as_matrix_single_channel_from_multi_cropped(self):
     """
     Same as previous test but with crop region provided.
     """
     # Load image normally, assumed functional (see above)
     mat_rgb_cropped = GdalImageReader()\
         .load_as_matrix(GH_CROPPED_FILE_ELEMENT)
     mat_b_cropped = GdalImageReader(channel_order='b')\
         .load_as_matrix(GH_FILE_ELEMENT, pixel_crop=GH_CROPPED_BBOX)
     assert mat_b_cropped.ndim == 2
     assert mat_b_cropped.shape == (100, 100)
     numpy.testing.assert_allclose(mat_b_cropped, mat_rgb_cropped[:, :, 2])
Example #6
0
 def test_load_as_matrix_single_channel_from_multi(self):
     """
     Test that when requesting a single channel we get back an ndim=2 matrix
     instead of a matrix with a 1-valied dimension.
     """
     # Load image normally, assumed functional (see above)
     mat_rgb = GdalImageReader().load_as_matrix(GH_FILE_ELEMENT)
     mat_b = GdalImageReader(channel_order='b')\
         .load_as_matrix(GH_FILE_ELEMENT)
     assert mat_b.shape == (600, 512)
     assert mat_b.ndim == 2
     numpy.testing.assert_allclose(mat_b, mat_rgb[:, :, 2])
Example #7
0
 def test_load_as_matrix_with_channel_order_invalid(self):
     """
     Test that we error when the requested channel order cannot be applied to
     the data given.
     """
     # We know that the GH_FILE_ELEMENT image is an RGB format image.
     msg = "Data element did not provide channels required"
     with pytest.raises(RuntimeError, match=msg):
         GdalImageReader(channel_order=[gdal_io.gdal.GCI_CyanBand])\
             .load_as_matrix(GH_FILE_ELEMENT)
     with pytest.raises(RuntimeError, match=msg):
         # Same as above, but with abbreviation
         GdalImageReader(channel_order='c')\
             .load_as_matrix(GH_FILE_ELEMENT)
Example #8
0
    def test_load_as_matrix_channel_reorder(self):
        """
        Test correctly loading image with channels reordered as requested.
        """
        # Load image normally, assumed functional (see above)
        mat_rgb = GdalImageReader().load_as_matrix(GH_FILE_ELEMENT)
        mat_brg = GdalImageReader(channel_order='brg')\
            .load_as_matrix(GH_FILE_ELEMENT)
        numpy.testing.assert_allclose(mat_brg, mat_rgb[:, :, [2, 0, 1]])

        # Duplicate bands? Because we can?
        mat_bgrgb = GdalImageReader(channel_order='bgrbg')\
            .load_as_matrix(GH_FILE_ELEMENT)
        numpy.testing.assert_allclose(mat_bgrgb, mat_rgb[:, :,
                                                         [2, 1, 0, 2, 1]])
Example #9
0
 def test_init_channel_order_invalid_abbreviation_char(self):
     """
     Test that exception is raise upon construction with an unknown channel
     order abbreviation.
     """
     msg = 'Invalid abbreviation character'
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order='!')
     # Check that we catch it among other valid characters
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order='rg!')
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order='!gb')
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order='r!b')
Example #10
0
 def test_init_channel_order_invalid_gci_integer(self):
     """
     Test that we catch integers that are not reported as supported constants
     by inspection of GDAL module values.
     """
     # We know (as of gdal 2.4.0) that 99 is not a valid GCI.
     msg = "Invalid GDAL band integer values given"
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order=[99])
     # Check that we catch it among other valid characters
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order=[3, 4, 99])
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order=[3, 99, 5])
     with pytest.raises(ValueError, match=msg):
         GdalImageReader(channel_order=[99, 4, 5])
Example #11
0
    def test_load_as_matrix_with_crop(self):
        """
        Test that the image is loaded with the correct crop region.

        We load two images: the original with a crop specified, and a
        pre-cropped image. The results of each load should be the same,
        indicating the correct region from the source image is extracted.
        """
        assert \
            GH_FILE_ELEMENT.get_bytes() != GH_CROPPED_FILE_ELEMENT.get_bytes()
        reader = GdalImageReader(
            load_method=GdalImageReader.LOAD_METHOD_TEMPFILE)
        cropped_actual = reader.load_as_matrix(GH_FILE_ELEMENT,
                                               pixel_crop=GH_CROPPED_BBOX)
        cropped_expected = reader.load_as_matrix(GH_CROPPED_FILE_ELEMENT)
        # noinspection PyTypeChecker
        numpy.testing.assert_allclose(cropped_actual, cropped_expected)
Example #12
0
 def test_init_vsimem_req_gdal_2_pass(self, m_osgeo):
     """
     Test that we do NOT get an error when using load_method='vsimem'
     and GDAL reports a version greater than 2.
     """
     # Mock a GDAL version greater than 2.
     m_osgeo.__version__ = "2.4.0"
     GdalImageReader(load_method=GdalImageReader.LOAD_METHOD_VSIMEM)
Example #13
0
 def test_load_as_matrix_empty_data(self):
     """
     Test that we catch and do not load an empty data element.
     """
     empty_de = DataMemoryElement(readonly=True, content_type='image/png')
     assert empty_de.is_empty()
     msg = "GdalImageReader cannot load 0-sized data"
     with pytest.raises(ValueError, match=msg):
         GdalImageReader().load_as_matrix(empty_de)
Example #14
0
    def test_serialization(self):
        """
        Test that we can serialize and deserialize the algorithm, maintaining
        configuration responses.
        """
        expected_load_method = GdalImageReader.LOAD_METHOD_TEMPFILE
        expected_channel_order = [3, 5, 4]
        inst1 = GdalImageReader(load_method=expected_load_method,
                                channel_order=expected_channel_order)

        expected_config = {'load_method': expected_load_method,
                           'channel_order': expected_channel_order}
        assert inst1.get_config() == expected_config

        buff = pickle.dumps(inst1)
        #: :type: GdalImageReader
        inst2 = pickle.loads(buff)
        assert inst2.get_config() == expected_config
Example #15
0
def test_GdalImageReader_usable():
    """
    Test that GdalImageReader class reports as usable when GDAL is importable.
    """
    # Mock module value of ``osgeo`` to something not None to simulate
    # something having been imported.
    with mock.patch.dict('smqtk.algorithms.image_io.gdal_io.__dict__',
                         {'osgeo': object()}):
        assert GdalImageReader.is_usable() is True
Example #16
0
    def test_load_as_matrix_channel_reorder_cropped(self):
        """
        Same as previous test but with crop region provided.
        """
        # Load image normally, assumed functional (see above)
        mat_rgb = GdalImageReader().load_as_matrix(GH_CROPPED_FILE_ELEMENT)
        mat_brg = GdalImageReader(channel_order='brg') \
            .load_as_matrix(GH_FILE_ELEMENT, pixel_crop=GH_CROPPED_BBOX)
        assert mat_brg.ndim == 3
        assert mat_brg.shape == (100, 100, 3)
        numpy.testing.assert_allclose(mat_brg, mat_rgb[:, :, [2, 0, 1]])

        # Duplicate bands? Because we can?
        mat_bgrggb = GdalImageReader(channel_order='bgrggb') \
            .load_as_matrix(GH_FILE_ELEMENT, pixel_crop=GH_CROPPED_BBOX)
        assert mat_bgrggb.ndim == 3
        assert mat_bgrggb.shape == (100, 100, 6)
        numpy.testing.assert_allclose(mat_bgrggb, mat_rgb[:, :,
                                                          [2, 1, 0, 1, 1, 2]])
Example #17
0
 def test_init_bad_load_method(self):
     """
     Test that passing a load_method string that is not one of the
     expected values raises a ValueError.
     """
     with pytest.raises(ValueError, match=r"Load method provided not a "
                                          r"valid value \(given 'not a "
                                          r"valid method'\)\. Must be one "
                                          r"of: "):
         GdalImageReader(load_method="not a valid method")
Example #18
0
    def test_load_as_matrix_tempfile(self):
        """
        Test that whole image is loaded successfully using tempfile loader.
        """
        wrapped_temp_loader = mock.MagicMock(wraps=load_dataset_tempfile)
        wrapped_vsimem_loader = mock.MagicMock(wraps=load_dataset_vsimem)

        with mock.patch.dict(GdalImageReader.LOAD_METHOD_CONTEXTMANAGERS, {
                    GdalImageReader.LOAD_METHOD_TEMPFILE: wrapped_temp_loader,
                    GdalImageReader.LOAD_METHOD_VSIMEM: wrapped_vsimem_loader
                }):
            # Using tempfile load method
            reader = GdalImageReader(
                load_method=GdalImageReader.LOAD_METHOD_TEMPFILE
            )
            mat = reader._load_as_matrix(GH_FILE_ELEMENT)
            assert mat.shape == (600, 512, 3)

        wrapped_temp_loader.assert_called_once_with(GH_FILE_ELEMENT)
        wrapped_vsimem_loader.assert_not_called()
Example #19
0
 def test_configuration(self):
     """
     Test configuration using helper
     """
     expected_load_method = GdalImageReader.LOAD_METHOD_TEMPFILE
     expected_channel_order = [3, 5, 4]
     i = GdalImageReader(load_method=expected_load_method,
                         channel_order=expected_channel_order)
     for inst in configuration_test_helper(i):  # type: GdalImageReader
         assert inst._load_method == expected_load_method
         assert inst._channel_order == expected_channel_order
Example #20
0
 def test_init_vsimem_req_gdal_2_fail(self, m_osgeo):
     """
     Test that we get a RuntimeError when using load_method='vsimem' and
     the current GDAL wrapper version is < 2.
     """
     # Mock a GDAL version less than 2.
     m_osgeo.__version__ = "1.11.0"
     with pytest.raises(RuntimeError,
                        match=r"Load method '{}' was specified, "
                        r"but required GDAL version of 2 is not "
                        r"satisfied \(imported version: {}\)\.".format(
                            GdalImageReader.LOAD_METHOD_VSIMEM, "1.11.0")):
         GdalImageReader(load_method=GdalImageReader.LOAD_METHOD_VSIMEM)
Example #21
0
def test_GdalImageReader_not_usable_missing_osgeo():
    """
    Test that class reports as not usable when GDAL is not importable (set
    to None in module).
    """
    # Catch expected warnings to not pollute output.
    with warnings.catch_warnings():
        warnings.filterwarnings('ignore', category=UserWarning)

        # Mock module value of ``osgeo`` to None.
        with mock.patch.dict('smqtk.algorithms.image_io.gdal_io.__dict__',
                             {'osgeo': None}):
            assert GdalImageReader.is_usable() is False
Example #22
0
    def test_load_as_matrix_vsimem(self):
        """
        Test that whole image is loaded successfully using vsimem loader.
        """
        if LooseVersion(osgeo.__version__).version[0] < 2:
            pytest.skip("Skipping VSIMEM test because GDAL version < 2")

        wrapped_temp_loader = mock.MagicMock(wraps=load_dataset_tempfile)
        wrapped_vsimem_loader = mock.MagicMock(wraps=load_dataset_vsimem)

        with mock.patch.dict(GdalImageReader.LOAD_METHOD_CONTEXTMANAGERS, {
                    GdalImageReader.LOAD_METHOD_TEMPFILE: wrapped_temp_loader,
                    GdalImageReader.LOAD_METHOD_VSIMEM: wrapped_vsimem_loader
                }):
            # Using VSIMEM load method
            reader = GdalImageReader(
                load_method=GdalImageReader.LOAD_METHOD_VSIMEM
            )
            mat = reader._load_as_matrix(GH_FILE_ELEMENT)
            assert mat.shape == (600, 512, 3)

        wrapped_temp_loader.assert_not_called()
        wrapped_vsimem_loader.assert_called_once_with(GH_FILE_ELEMENT)
Example #23
0
    def test_valid_content_types(self, m_ggdsm):
        """
        Test that valid_content_types refers to the helper method and
        returns the same thing.

        Mocking (wrapping) `get_gdal_driver_supported_mimetypes` in order check
        that it is being called under the hood.
        """
        expected_content_types = get_gdal_driver_supported_mimetypes()

        actual_content_types = GdalImageReader().valid_content_types()

        m_ggdsm.assert_called_once_with()
        assert actual_content_types == expected_content_types
Example #24
0
def test_GdalImageReader_not_usable_missing_osgeo():
    """
    Test that class reports as not usable when GDAL is not importable (set
    to None in module).
    """
    # Catch expected warnings to not pollute output.
    with warnings.catch_warnings():
        warnings.filterwarnings('ignore', category=UserWarning)

        # Mock module value of ``osgeo`` to None.
        with mock.patch.dict('smqtk.algorithms.image_io.gdal_io.__dict__',
                             {'osgeo': None}):
            assert GdalImageReader.is_usable() is False


@pytest.mark.skipif(not GdalImageReader.is_usable(),
                    reason="GdalImageReader implementation is not usable in "
                           "the current environment.")
class TestGdalImageReader (unittest.TestCase):
    """
    Tests for ``GdalImageReader`` class.

    If this was not skipped, ``osgeo`` must have been importable.
    """

    def test_init_default(self):
        """
        Test that construction with default parameters works.
        """
        GdalImageReader()
Example #25
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 = GdalImageReader()

        # 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(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(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(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(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(GH_FILE_ELEMENT, pixel_crop=bb)
Example #26
0
 def test_init_channel_order_lower_case(self):
     """
     Test that channel order if provided as string is cast to lower case.
     """
     assert GdalImageReader(channel_order='rGB')._channel_order == \
         "rgb"
Example #27
0
 def test_init_default(self):
     """
     Test that construction with default parameters works.
     """
     GdalImageReader()