def test_gdal_buildvrt_concatenate(self):
        from StartMaja.Common import FileSystem
        paths = []
        for i in range(1, 3, 1):
            img = np.ones((i, i, 2), np.int16) * i
            path = os.path.join(os.getcwd(), "test_gdal_merge_%s.tif" % i)
            ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
            self.assertTrue(os.path.exists(path))
            paths.append(path)
        empty = os.path.join(os.getcwd(), "empty.vrt")
        driver = ImageTools.gdal_buildvrt(*paths, dst=empty,
                                          separate=True,
                                          srcnodata=0)
        expected = np.array([[[1, 0],
                              [0, 0]],
                             [[2, 2],
                              [2, 2]]], dtype=np.int16)

        np.testing.assert_almost_equal(driver.array, expected)
        self.assertEqual(driver.nodata_value, 0)
        self.assertEqual(driver.epsg, 32631)
        [FileSystem.remove_file(path) for path in paths]
        FileSystem.remove_file(empty)
        [self.assertFalse(os.path.exists(path)) for path in paths]
        self.assertFalse(os.path.exists(empty))
Example #2
0
 def test_srtm_get_maja_format_s2_31tcj(self):
     site = SiteInfo.Site("T31TCJ",
                          32631,
                          res_x=90,
                          res_y=-90,
                          ul=(300000.000, 4900020.000),
                          lr=(409800.000, 4790220.000))
     dem_dir = os.path.join(os.getcwd(),
                            "test_srtm_get_maja_format_s2_31tcj")
     s = SRTM.SRTM(site,
                   dem_dir=dem_dir,
                   raw_dem=self.raw_srtm,
                   raw_gsw=self.raw_gsw,
                   wdir=dem_dir)
     self.assertTrue(os.path.isdir(dem_dir))
     hdr, dbl = s.to_maja_format(platform_id="S2_",
                                 mission_field="SENTINEL-2_",
                                 coarse_res=(240, -240),
                                 mnt_resolutions=[{
                                     "name": "R1",
                                     "val": "10 -10"
                                 }, {
                                     "name": "R2",
                                     "val": "20 -20"
                                 }])
     self.assertTrue(os.path.exists(hdr))
     self.assertTrue(os.path.isdir(dbl))
     FileSystem.remove_directory(dem_dir)
     FileSystem.remove_file(hdr)
    def test_override_array(self):
        img = np.ones((self.height, self.width), np.int16)
        img_new = np.array(np.arange(0, 40200).reshape(201, 200),
                           dtype=np.uint8)
        path = os.path.join(os.getcwd(), "test_write_read_geotiff.tif")
        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        self.assertTrue(os.path.exists(path))

        ds = GDalDatasetWrapper.from_file(path)
        self.assertTrue((ds.array == img).all())
        self.assertEqual(ds.geotransform, self.coordinates)
        self.assertEqual(ds.projection.replace(" ", ""),
                         self.projection.replace(" ", ""))
        self.assertIsNone(ds.nodata_value)
        self.assertEqual(ds.epsg, 32631)
        ds_new = GDalDatasetWrapper(ds=ds.get_ds(),
                                    array=img_new,
                                    nodata_value=123)
        FileSystem.remove_file(path)
        np.testing.assert_almost_equal(img_new, ds_new.array)
        self.assertEqual(ds_new.geotransform, self.coordinates)
        self.assertEqual(ds_new.projection.replace(" ", ""),
                         self.projection.replace(" ", ""))
        self.assertEqual(ds_new.nodata_value, 123)
        self.assertEqual(ds_new.epsg, 32631)
        self.assertFalse(os.path.exists(path))
    def test_gdal_tile_untile(self):
        img = np.arange(0., 100.).reshape((10, 10))
        path = os.path.join(os.getcwd(), "test_gdal_retile.tif")
        tile_folder = os.path.join(os.getcwd(), "tiled")
        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        # Add parasitic file - It should not cause problems
        path_parasite = os.path.join(tile_folder, "tile_01_01.tif")
        FileSystem.create_directory(tile_folder)
        ImageIO.write_geotiff(img, path_parasite, self.projection, self.coordinates)
        ds_in = GDalDatasetWrapper.from_file(path)
        self.assertTrue(os.path.exists(path))
        tiles = ImageTools.gdal_retile(ds_in, tile_folder,
                                       TileWidth=2,
                                       TileHeight=2,
                                       Overlap=1)
        self.assertTrue(os.path.isdir(tile_folder))
        self.assertEqual(len(tiles), 81)
        img_read = np.array(ImageIO.tiff_to_array(tiles[-1]))
        expected = np.array([[88, 89],
                             [98, 99]])
        # Some gdal_retile versions are producing the following image:
        # [[87, 89], [97, 99]].
        np.testing.assert_allclose(expected, img_read, atol=1)

        # Untile
        ds_untiled = ImageTools.gdal_buildvrt(*tiles)
        np.testing.assert_allclose(img, ds_untiled.array, atol=1)
        FileSystem.remove_file(path)
        FileSystem.remove_directory(tile_folder)
 def test_write_read_geotiff_kwoptions(self):
     img = np.ones((self.height, self.width), np.int16)
     nodata = 42
     path = os.path.join(os.getcwd(), "test_write_read_geotiff.tif")
     ImageIO.gdal_write("GTiff",
                        img,
                        path,
                        self.projection,
                        self.coordinates,
                        options=["COMPRESS=DEFLATE"],
                        nodata=nodata)
     self.assertTrue(os.path.exists(path))
     arr, ds = ImageIO.tiff_to_array(path, array_only=False)
     self.assertTrue((arr == img).all())
     self.assertEqual(
         nodata,
         gdal.Info(ds, format="json")["bands"][0]["noDataValue"])
     self.assertEqual(
         gdal.Info(
             ds,
             format="json")["metadata"]["IMAGE_STRUCTURE"]["COMPRESSION"],
         "DEFLATE")
     self.assertEqual(ds.GetGeoTransform(), self.coordinates)
     # Compare projections by removing all spaces cause of multiline string
     self.assertEqual(ds.GetProjection().replace(" ", ""),
                      self.projection.replace(" ", ""))
     FileSystem.remove_file(path)
     self.assertFalse(os.path.exists(path))
 def test_get_s2_epsg_code(self):
     epsg_ref = 32631
     projection = 'PROJCS["WGS 84 / UTM zone 31N",\
                     GEOGCS["WGS 84",DATUM["WGS_1984",\
                     SPHEROID["WGS 84",6378137,298.257223563,\
                     AUTHORITY["EPSG","7030"]],\
                     AUTHORITY["EPSG","6326"]],\
                     PRIMEM["Greenwich",0,\
                     AUTHORITY["EPSG","8901"]],\
                     UNIT["degree",0.0174532925199433,\
                     AUTHORITY["EPSG","9122"]],\
                     AUTHORITY["EPSG","4326"]],\
                     PROJECTION["Transverse_Mercator"],\
                     PARAMETER["latitude_of_origin",0],\
                     PARAMETER["central_meridian",3],\
                     PARAMETER["scale_factor",0.9996],\
                     PARAMETER["false_easting",500000],\
                     PARAMETER["false_northing",0],\
                     UNIT["metre",1,AUTHORITY["EPSG","9001"]],\
                     AXIS["Easting",EAST],AXIS["Northing",NORTH],\
                     AUTHORITY["EPSG","%s"]]' % epsg_ref
     img = np.ones((self.height, self.width), np.int16)
     path = os.path.join(os.getcwd(), "test_epsg.tif")
     ImageIO.write_geotiff(img, path, projection, self.coordinates)
     self.assertTrue(os.path.exists(path))
     ds = GDalDatasetWrapper.from_file(path)
     epsg_new = ds.epsg
     self.assertEqual(epsg_new, epsg_ref)
     FileSystem.remove_file(path)
     self.assertFalse(os.path.exists(path))
Example #7
0
 def tearDownClass(cls):
     from StartMaja.Common import FileSystem
     # In case there's duplicates, remove them:
     FileSystem.remove_directory(cls.product_root)
     FileSystem.remove_file(cls.folders_file)
     FileSystem.remove_directory(cls.cams)
     FileSystem.remove_directory(cls.mnt.dbl)
     FileSystem.remove_file(cls.mnt.hdr)
Example #8
0
 def test_create_remove_file(self):
     path = os.path.join(os.getcwd(), "test_create_remove_file")
     self.assertFalse(os.path.exists(path))
     TestFunctions.touch(path)
     self.assertTrue(os.path.exists(path))
     self.assertTrue(os.path.isfile(path))
     FileSystem.remove_file(path)
     self.assertFalse(os.path.exists(path))
Example #9
0
 def __clean_up(self):
     """
     Clean up the download directory.
     :return:
     """
     from StartMaja.Common import FileSystem
     FileSystem.remove_directory(self.temp_folder)
     FileSystem.remove_file(self.lut_archive)
     FileSystem.remove_file(self.gipp_archive)
 def test_get_nodata(self):
     expected_nodata = 42.0
     img = np.ones((self.height, self.width), np.int16)
     path = os.path.join(os.getcwd(), "test_get_nodata_init.tif")
     ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
     ds = ImageTools.gdal_buildvrt(path, VRTNodata=expected_nodata)
     self.assertEqual(expected_nodata, ds.nodata_value)
     np.testing.assert_almost_equal(ds.nodata_mask, np.ones_like(img))
     FileSystem.remove_file(path)
     self.assertFalse(os.path.exists(path))
 def test_get_utm_description(self):
     img = np.ones((self.height, self.width), np.int16)
     path = os.path.join(os.getcwd(), "test_get_utm_description.tif")
     ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
     self.assertTrue(os.path.exists(path))
     ds = GDalDatasetWrapper.from_file(path)
     utm = ds.utm_description
     utm_expected = "WGS 84 / UTM zone 31N"
     self.assertEqual(utm_expected, utm)
     FileSystem.remove_file(path)
     self.assertFalse(os.path.exists(path))
    def test_gdal_buildvrt(self):
        path = os.path.join(os.getcwd(), "test_gdal_buildvrt.tif")
        vrt = os.path.join(os.getcwd(), "test_vrt.vrt")
        img = np.arange(-4, 5).reshape(3, 3) / 5

        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        self.assertTrue(os.path.exists(path))
        driver = ImageTools.gdal_buildvrt(path, dst=vrt)
        self.assertTrue(os.path.exists(vrt))
        np.testing.assert_almost_equal(driver.array, img)
        FileSystem.remove_file(vrt)
        FileSystem.remove_file(path)
    def test_get_resolution(self):
        img = np.ones((self.height, self.width), np.int16)
        path = os.path.join(os.getcwd(), "test_get_resolution.tif")
        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        self.assertTrue(os.path.exists(path))

        ds = GDalDatasetWrapper.from_file(path)
        res_expected = (self.coordinates[1], self.coordinates[-1])
        self.assertEqual(res_expected, ds.resolution)

        FileSystem.remove_file(path)
        self.assertFalse(os.path.exists(path))
 def test_get_models_cams(self):
     from StartMaja.Common import FileSystem
     g = GippSet(self.root, "sentinel2", "tm", cams=True)
     with self.assertRaises(ValueError):
         g.get_models()
     self.assertFalse(g.check_completeness())
     g.download()
     self.assertTrue(g.check_completeness())
     self.assertTrue(g.get_models() in g.expected_models)
     FileSystem.remove_file(os.path.join(self.root, "wget-log"))
     if not os.getcwd() == g.out_path:
         FileSystem.remove_directory(g.out_path)
         self.assertFalse(os.path.exists(g.out_path))
    def test_get_ul_lr(self):
        img = np.ones((1000, 1000), np.int16)
        path = os.path.join(os.getcwd(), "test_get_ul_lr.tif")
        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        self.assertTrue(os.path.exists(path))

        ds = GDalDatasetWrapper.from_file(path)
        ulx, uly, lrx, lry = ds.ul_lr
        self.assertEqual((ulx, uly), (300000.0, 4900020.0))
        self.assertEqual((lrx, lry), (310000.0, 4890020.0))
        self.assertEqual(ds.extent, (300000.0, 4890020.0, 310000.0, 4900020.0))
        FileSystem.remove_file(path)
        self.assertFalse(os.path.exists(path))
    def test_write_read_geotiff(self):
        img = np.ones((self.height, self.width), np.int16)
        path = os.path.join(os.getcwd(), "test_write_read_geotiff.tif")
        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        self.assertTrue(os.path.exists(path))

        arr, ds = ImageIO.tiff_to_array(path, array_only=False)
        self.assertTrue((arr == img).all())
        self.assertEqual(ds.GetGeoTransform(), self.coordinates)
        # Compare projections by removing all spaces cause of multiline string
        self.assertEqual(ds.GetProjection().replace(" ", ""),
                         self.projection.replace(" ", ""))
        FileSystem.remove_file(path)
        self.assertFalse(os.path.exists(path))
    def test_write_read_memory(self):
        img = np.ones((self.height, self.width), np.int16)
        path = "/vsimem/test_write_read_memory.tif"
        ds = ImageIO.write_to_memory(img, path, self.projection,
                                     self.coordinates)

        arr = ds.ReadAsArray()
        self.assertTrue((arr == img).all())
        self.assertEqual(ds.GetGeoTransform(), self.coordinates)
        # Compare projections by removing all spaces cause of multiline string
        self.assertEqual(ds.GetProjection().replace(" ", ""),
                         self.projection.replace(" ", ""))
        ds = None  # Always remember to dereference :)
        FileSystem.remove_file(path)
 def test_faulty_geotransform_projection(self):
     coordinates = (652594.9112913811, 10.00887639510383, 0,
                    5072876.717295351, 0)  # Missing one value
     projection = ''  # Empty
     height = 200
     width = 100
     img = np.ones((height, width), np.int16)
     path = os.path.join(os.getcwd(),
                         "test_faulty_geotransform_projection.tif")
     # Check geotransform wrong:
     with self.assertRaises(TypeError):
         ImageIO.write_geotiff(img, path, projection, coordinates)
     FileSystem.remove_file(path)
     self.assertFalse(os.path.exists(path))
Example #19
0
 def tearDown(self):
     FileSystem.remove_directory(self.wdir)
     FileSystem.remove_directory(self.outdir)
     FileSystem.remove_directory(self.l1.fpath)
     FileSystem.remove_directory(self.l2.fpath)
     for p in self.l1_list:
         FileSystem.remove_directory(p.fpath)
     for p in self.other_l1:
         FileSystem.remove_directory(p.fpath)
     for p in self.other_l2:
         FileSystem.remove_directory(p.fpath)
     FileSystem.remove_directory(self.cams.dbl)
     FileSystem.remove_file(self.cams.hdr)
     FileSystem.remove_directory(self.gipp_dir)
 def test_gdal_translate(self):
     img = np.ones((self.height, self.width, 2), np.int16)
     path = os.path.join(os.getcwd(), "test_gdal_translate.tif")
     scaled = os.path.join(os.getcwd(), "scaled.tif")
     out_resolution = (20, -20)
     ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
     self.assertTrue(os.path.exists(path))
     ds = ImageTools.gdal_translate(path, scaled,
                                    tr=" ".join([str(i) for i in out_resolution]),
                                    scale="0 1 0 255")
     self.assertEqual(ds.resolution, out_resolution)
     self.assertEqual(ds.array.shape, (self.height // 2, self.width // 2, 2))
     np.testing.assert_almost_equal(ds.array, 255)
     FileSystem.remove_file(path)
     FileSystem.remove_file(scaled)
    def test_write_read_geotiff(self):
        img = np.ones((self.height, self.width), np.int16)
        path = os.path.join(os.getcwd(), "test_write_read_geotiff.tif")
        ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
        self.assertTrue(os.path.exists(path))

        ds = GDalDatasetWrapper.from_file(path)
        self.assertTrue((ds.array == img).all())
        self.assertEqual(ds.geotransform, self.coordinates)
        # Compare projections by removing all spaces cause of multiline string
        self.assertEqual(ds.projection.replace(" ", ""),
                         self.projection.replace(" ", ""))
        self.assertIsNone(ds.nodata_value)
        self.assertEqual(ds.epsg, 32631)
        FileSystem.remove_file(path)
        self.assertFalse(os.path.exists(path))
def run_tiling(ds_or_path, **kwargs):
    """
    Run the tiling process

    :param ds_or_path: The :class:`gdal.Dataset` or a path to a file on disk to be tiled
    :type ds_or_path: :class:`gdal.Dataset` or str
    :param kwargs: Optional arguments.
    :return: Creates the tiles in the given location.
    """
    cmd_dict = {"Verbose": "-v", "Quiet": "-q", "CreationOptions": "-co", "TileSize": "-ps",
                "Overlap": "-overlap", "Format": "-of", "BandType": "-ot", "TileIndexFieldName": "-tileIndexField",
                "TileIndexName": "-tileIndex", "CsvDelimiter": "-csvDelim", "Source_SRS": "-s_srs",
                "TargetDir": "-targetDir", "-ResamplingMethod": "-r", "Levels": "-levels",
                "PyramidOnly": "-pyramidOnly", "UseDirForEachRow": "-useDirForEachRow"}

    gdal.AllRegister()
    gdal.UseExceptions()

    options = []

    if type(ds_or_path) != str:
        tmppath = os.path.join(tempfile.gettempdir(), next(tempfile._get_candidate_names()))
        ds_or_path.write(tmppath)
        del_tmp = True
    else:
        tmppath = ds_or_path
        del_tmp = False
    tx, ty = None, None
    for key in kwargs.keys():
        if key == "TileWidth":
            ty = kwargs[key]
        elif key == "TileHeight":
            tx = kwargs[key]
        else:
            options += [cmd_dict[key], kwargs[key]]
    if not tx or not ty:
        raise ValueError("Must provide tile width and height: (%s, %s)" % (ty, tx))
    options += [cmd_dict["TileSize"], "%s %s" % (ty, tx)]
    options += [tmppath]
    assert FileSystem.run_external_app("gdal_retile.py", options) == 0, "Error running gdal_retile"
    bname = os.path.basename(tmppath)
    outpath = kwargs["TargetDir"]
    # TODO Discard previously written files from `find`:
    files_written = sorted(FileSystem.find(r"%s_\d+_\d+.tif" % bname, path=outpath))
    if del_tmp:
        FileSystem.remove_file(tmppath)
    return files_written
 def test_write_and_get_xpath(self):
     from xml.etree import ElementTree
     from StartMaja.Common import FileSystem
     file_path = os.path.join(self.root, "dummy_xml.xml")
     mission_expected = "DummyMission"
     xpath = "./Fixed_Header/Mission"
     root = ElementTree.Element("Earth_Explorer_Header")
     sub = ElementTree.SubElement(root, "Fixed_Header")
     ElementTree.SubElement(sub, "Mission").text = mission_expected
     ElementTree.SubElement(root, "Variable_Header")
     XMLTools.write_xml(root, file_path)
     self.assertTrue(os.path.exists(file_path))
     mission_calculated = XMLTools.get_xpath(file_path, xpath)[0].text
     mission_calculated_2 = XMLTools.get_single_xpath(file_path, xpath)
     self.assertEqual(mission_calculated, mission_expected)
     self.assertEqual(mission_expected, mission_calculated_2)
     FileSystem.remove_file(file_path)
 def test_gdal_warp(self):
     img = np.ones((self.height, self.width, 2), np.int16)
     img_rescaled = np.ones((int(self.height/2), int(self.width/2), 2), np.int16)
     out_resolution = (20, -20)
     path = os.path.join(os.getcwd(), "test_gdal_warp.tif")
     scaled = os.path.join(os.getcwd(), "res_changed.tif")
     ImageIO.write_geotiff(img, path, self.projection, self.coordinates)
     self.assertTrue(os.path.exists(path))
     ds = ImageTools.gdal_warp(path, scaled,
                               tr=" ".join(str(e) for e in out_resolution),
                               r="max", q=True)
     self.assertTrue(os.path.isfile(scaled))
     self.assertEqual(ds.resolution, out_resolution)
     self.assertEqual(ds.array.shape, (self.height // 2, self.width // 2, 2))
     np.testing.assert_almost_equal(ds.array, img_rescaled)
     FileSystem.remove_file(path)
     FileSystem.remove_file(scaled)
    def test_merge_then_translate(self):
        datasets = []
        init = np.zeros((2, 2), np.int16)
        path = os.path.join(os.getcwd(), "test_gdal_merge.tif")
        ImageIO.write_geotiff(init, path, self.projection, self.coordinates)
        ds_in = GDalDatasetWrapper.from_file(path)
        for i in range(1, 3, 1):
            img = np.ones((i*2, i*2), np.int16) * i
            ds_n = GDalDatasetWrapper(ds=ds_in.get_ds(), array=img)
            self.assertTrue(os.path.exists(path))
            datasets.append(ds_n)
        ds_merged = ImageTools.gdal_merge(*datasets, dst="out.tif",
                                          separate=True,
                                          q=True,
                                          a_nodata=0)
        # Array of shape (4, 4, 2):
        expected = np.array([[[1, 2],
                              [1, 2],
                              [0, 2],
                              [0, 2]],
                             [[1, 2],
                              [1, 2],
                              [0, 2],
                              [0, 2]],
                             [[0, 2],
                              [0, 2],
                              [0, 2],
                              [0, 2]],
                             [[0, 2],
                              [0, 2],
                              [0, 2],
                              [0, 2]]], dtype=np.int16)
        FileSystem.remove_file("out.tif")
        np.testing.assert_equal(expected.dtype, ds_merged.array.dtype)
        np.testing.assert_almost_equal(expected, ds_merged.array)
        self.assertEqual(ds_merged.nodata_value, 0)
        self.assertEqual(ds_merged.epsg, 32631)
        ds_translate = ImageTools.gdal_translate(ds_merged,
                                                 a_nodata=0)
        FileSystem.remove_file(path)

        np.testing.assert_equal(expected.dtype, ds_translate.array.dtype)
        np.testing.assert_almost_equal(ds_translate.array, expected)
        self.assertEqual(ds_translate.nodata_value, 0)
        self.assertEqual(ds_translate.epsg, 32631)
 def test_download_s2_muscate_nocams(self):
     from StartMaja.Common import FileSystem
     g = GippSet(self.root, "sentinel2", "muscate")
     self.assertFalse(g.check_completeness())
     g.download()
     self.assertTrue(g.check_completeness())
     n_l2comm = len(FileSystem.find("*L2COMM*", g.out_path))
     self.assertEqual(n_l2comm, 2)
     n_qltl = len(FileSystem.find("*CKQLTL*", g.out_path))
     self.assertEqual(n_qltl, 2)
     n_extl = len(FileSystem.find("*CKEXTL*", g.out_path))
     self.assertEqual(n_extl, 2)
     n_extl = len(FileSystem.find("*EEF", g.out_path))
     self.assertEqual(n_extl, 9)
     FileSystem.remove_file(os.path.join(self.root, "wget-log"))
     if not os.getcwd() == g.out_path:
         FileSystem.remove_directory(g.out_path)
         self.assertFalse(os.path.exists(g.out_path))
 def test_symlink(self):
     from StartMaja.Common import FileSystem
     g = GippSet(self.root, "sentinel2", "tm")
     self.assertFalse(g.check_completeness())
     g.download()
     self.assertTrue(g.check_completeness())
     symlink_dir = os.path.join(self.root, "symlinks")
     FileSystem.create_directory(symlink_dir)
     with self.assertRaises(ValueError):
         self.assertTrue(len(FileSystem.find("*EEF", symlink_dir)), 0)
     g.link(symlink_dir)
     self.assertEqual(len(FileSystem.find("*EEF", symlink_dir)), 15)
     FileSystem.remove_directory(symlink_dir)
     self.assertFalse(os.path.isdir(symlink_dir))
     FileSystem.remove_file(os.path.join(self.root, "wget-log"))
     if not os.getcwd() == g.out_path:
         FileSystem.remove_directory(g.out_path)
         self.assertFalse(os.path.exists(g.out_path))
def gdal_translate(src, dst=None, **options):
    """
    Translate a dataset.

    :param src: The input filename or dataset.
    :param dst: If specified, the output will be writen to
    the given path on a physical disk.
    Note: This overwrites a previous file at the same location.
    :return: A :class:`Common.GDalDatasetWrapper.GDalDatasetWrapper` object
    :rtype: `osgeo.gdal.dataset` or file on disk (see parameter ``dst``).
    """
    gdal_common_params = ["optfile", "config", "debug"]
    options_list = []
    for k, v in options.items():
        if k in gdal_common_params:
            options_list += ["--%s" % k, "%s" % v]
        elif type(v) is not bool:
            options_list += ["-%s" % k, "%s" % v]
        elif type(v) is bool and v is True:
            options_list.append("-%s" % k)
        else:
            pass
    options_list = " ".join(options_list)

    if type(src) == GDalDatasetWrapper:
        src = src.get_ds()
    # Remove previous existing file if writing to disk is enabled:
    if dst:
        FileSystem.remove_file(dst)
        # Note: De-allocation before file is actually written to disk
        # cf. https://gdal.org/api/python_gotchas.html
        _ = gdal.Translate(dst, src, options=options_list)
        _ = None
        ds_out = gdal.Open(dst)
    else:
        # Write directly into memory if no path specified (faster):
        dst = "/vsimem/" + uuid.uuid4().hex
        ds_out = gdal.Translate(dst, src, options=options_list)
    arr_bands_last = np.array(ds_out.ReadAsArray())
    if arr_bands_last.ndim == 3:
        arr_bands_last = np.moveaxis(arr_bands_last, 0, -1)
    return GDalDatasetWrapper(ds=ds_out, array=arr_bands_last)
    def test_gdal_merge_optfile(self):
        datasets, written = [], []
        init = np.zeros((2, 2), np.int16)
        path = os.path.join(os.getcwd(), "test_gdal_merge_optfile.tif")
        ImageIO.write_geotiff(init, path, self.projection, self.coordinates)
        ds_in = GDalDatasetWrapper.from_file(path)
        for i in range(1, 3, 1):
            img = np.ones((i*2, i*2), np.int16) * i
            ds_n = GDalDatasetWrapper(ds=ds_in.get_ds(), array=img)
            p_out = "test_gdal_merge_optfile_%s.tif" % i
            ImageIO.write_geotiff_existing(img, p_out, ds_in.get_ds())
            self.assertTrue(os.path.exists(path))
            datasets.append(ds_n)
            written.append(p_out)
        optfile = "test_gdal_merge_optfile.txt"
        with open(optfile, 'w') as file_handler:
            for item in written:
                file_handler.write("{}\n".format(item))

        ds_merged = ImageTools.gdal_merge(*datasets,
                                          q=True,
                                          a_nodata=0)
        ds_optfile = ImageTools.gdal_merge(optfile=optfile,
                                           q=True,
                                           a_nodata=0)
        # Array of shape (4, 4):
        expected = np.array([[2, 2, 2, 2],
                             [2, 2, 2, 2],
                             [2, 2, 2, 2],
                             [2, 2, 2, 2]], dtype=np.int16)

        FileSystem.remove_file(path)
        [FileSystem.remove_file(p) for p in written]
        FileSystem.remove_file(optfile)
        np.testing.assert_equal(expected.dtype, ds_merged.array.dtype)
        np.testing.assert_almost_equal(expected, ds_merged.array)
        self.assertEqual(ds_merged.nodata_value, 0)
        self.assertEqual(ds_merged.epsg, 32631)
        np.testing.assert_equal(expected.dtype, ds_optfile.array.dtype)
        np.testing.assert_almost_equal(expected, ds_optfile.array)
        self.assertEqual(ds_optfile.nodata_value, 0)
        self.assertEqual(ds_optfile.epsg, 32631)
    def setUpClass(cls):
        # Note those directories are not destroyed after executing tests.
        # This is in order to avoid multiple downloads amongst different test classes.
        FileSystem.create_directory(cls.raw_gsw)
        FileSystem.create_directory(cls.raw_eudem)

        # Setup dummy EuDEM file of reduced resolution
        arr = np.zeros((400, 400), dtype=np.float32)
        to_zip = [
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N20.TIF"),
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N20.TIF.ovr"),
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N20.TIF.aux.xml"),
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N20.TFw")
        ]
        write_geotiff(arr, to_zip[0], cls.projection, cls.geotransform_e30n20)
        [TestFunctions.touch(f) for f in to_zip[1:]]
        with zipfile.ZipFile(
                os.path.join(cls.raw_eudem, "eu_dem_v11_E30N20.zip"),
                'w') as zip_archive:
            for file in to_zip:
                zip_archive.write(file, compress_type=zipfile.ZIP_DEFLATED)
        FileSystem.remove_file(to_zip[0])

        # Setup dummy EuDEM file of reduced resolution
        arr = np.ones((400, 400), dtype=np.float32)
        # Add some other value to around half of the image
        arr[:, 260:] = 10
        to_zip = [
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N30.TIF"),
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N30.TIF.ovr"),
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N30.TIF.aux.xml"),
            os.path.join(cls.raw_eudem, "eu_dem_v11_E30N30.TFw")
        ]
        write_geotiff(arr, to_zip[0], cls.projection, cls.geotransform_e30n30)
        [TestFunctions.touch(f) for f in to_zip[1:]]
        with zipfile.ZipFile(
                os.path.join(cls.raw_eudem, "eu_dem_v11_E30N30.zip"),
                'w') as zip_archive:
            for file in to_zip:
                zip_archive.write(file, compress_type=zipfile.ZIP_DEFLATED)
        FileSystem.remove_file(to_zip[0])