예제 #1
0
def test_merge_does_not_uncover_masked_pixels():
    # See https://github.com/satellogic/telluric/issues/65
    affine = Affine.translation(0, 2) * Affine.scale(1, -1)

    rs_a = GeoRaster2(
        image=np.ma.masked_array(
            [[[100, 89], [100, 89]], [[110, 99], [110, 99]]],
            [[[False, True], [False, True]], [[False, True], [False, True]]],
            dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        band_names=['red', 'green'],
    )

    rs_b = GeoRaster2(
        image=np.array([[[0, 210], [0, 210]]], dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        band_names=['green'],
    )

    expected_image = np.ma.masked_array(
        [[[100, 89], [100, 89]], [[110, 99], [110, 99]]],
        [[[False, True], [False, True]], [[False, True], [False, True]]],
        dtype=np.uint8)

    result = merge_all([rs_a, rs_b],
                       rs_a.footprint()).limit_to_bands(['red', 'green'])

    assert_array_equal(np.ma.filled(result.image, 0),
                       np.ma.filled(expected_image, 0))
    assert_array_equal(result.image.mask, expected_image.mask)
예제 #2
0
def test_feature_collection_from_rasters():
    rasters_list = [
        GeoRaster2.open("./tests/data/raster/overlap1.tif"),
        GeoRaster2.open("./tests/data/raster/overlap2.tif")
    ]
    fc = FeatureCollection.from_georasters(rasters_list)
    assert fc.is_rasters_collection()
예제 #3
0
def test_join_use_mask_band():
    # https://github.com/OSGeo/gdal/issues/1148
    # The test checks the pixel at the coordinate of bottom left corner of the r2 raster is unmasked.
    r1 = GeoRaster2.open("tests/data/raster/overlap1.tif")
    r2 = GeoRaster2.open("tests/data/raster/overlap2.tif")
    joined = join([r1, r2])
    assert not joined.get(r2.corners()["bl"]).mask.all()
예제 #4
0
def test_rpcs_init():
    # test rpcs initilization by passing rpcs in different forms
    rpcs_dict = some_rpcs.to_dict()
    rpcs_dict = {k.upper(): v for k, v in rpcs_dict.items()}
    georaster1 = GeoRaster2(some_image_2d, rpcs=some_rpcs)
    georaster2 = GeoRaster2(some_image_2d, rpcs=rpcs_dict)
    assert georaster1.rpcs == georaster2.rpcs
    # rpcs defined as dictionary of str
    new_rpcs_dict = {}
    for k, v in rpcs_dict.items():
        if isinstance(v, float):
            new_rpcs_dict[k] = str(v)
        line_num_coeff = rpcs_dict['LINE_NUM_COEFF']
        new_rpcs_dict['LINE_NUM_COEFF'] = ' '.join(
            str(e) for e in line_num_coeff)
        line_den_coeff = rpcs_dict['LINE_DEN_COEFF']
        new_rpcs_dict['LINE_DEN_COEFF'] = ' '.join(
            str(e) for e in line_den_coeff)
        samp_num_coeff = rpcs_dict['SAMP_NUM_COEFF']
        new_rpcs_dict['SAMP_NUM_COEFF'] = ' '.join(
            str(e) for e in samp_num_coeff)
        samp_den_coeff = rpcs_dict['SAMP_DEN_COEFF']
        new_rpcs_dict['SAMP_DEN_COEFF'] = ' '.join(
            str(e) for e in samp_den_coeff)
    georaster3 = GeoRaster2(some_image_2d, rpcs=new_rpcs_dict)
    assert georaster2.rpcs == georaster3.rpcs
예제 #5
0
def rasters_for_testing_chunks():
    rasters = [
        GeoRaster2.open("tests/data/raster/overlap2.tif"),
        GeoRaster2.open("tests/data/raster/overlap2.tif")
    ]
    rasters[0].image
    return rasters
예제 #6
0
def test_get_tile_merge_tiles(tile):
    raster1_path = './tests/data/raster/overlap1.tif'
    raster2_path = './tests/data/raster/overlap2.tif'
    raster1 = GeoRaster2.open(raster1_path)
    raster2 = GeoRaster2.open(raster2_path)

    features = [
        GeoFeature(raster1.footprint().reproject(new_crs=WGS84_CRS),
                   {'raster_url': raster1_path, 'created': datetime.now()}),
        GeoFeature(raster2.footprint().reproject(new_crs=WGS84_CRS),
                   {'raster_url': raster2_path, 'created': datetime.now()}),
    ]

    fc = FeatureCollection(features)
    bounds = mercantile.xy_bounds(*tile)
    eroi = GeoVector.from_bounds(xmin=bounds.left, xmax=bounds.right,
                                 ymin=bounds.bottom, ymax=bounds.top,
                                 crs=WEB_MERCATOR_CRS)
    expected_tile = merge_all([raster1.get_tile(*tile), raster2.get_tile(*tile)], roi=eroi)
    merged = fc.get_tile(*tile, sort_by='created')
    if merged is not None:
        assert merged == expected_tile
    else:
        assert expected_tile.image.mask.all()
        assert (expected_tile.image.data == 0).all()
예제 #7
0
def test_tags():
    with TemporaryDirectory() as folder:
        path = os.path.join(folder, 'test.tif')
        some_raster_multiband.save(path, tags={'foo': 'bar'}, factors=default_factors)

        assert GeoRaster2.tags(path) == {'AREA_OR_POINT': 'Area', 'foo': 'bar',
                                         'telluric_band_names': '["r", "g", "b"]'}  # namespace=default
        assert GeoRaster2.tags(path, 'IMAGE_STRUCTURE') == {'COMPRESSION': 'LZW', 'INTERLEAVE': 'PIXEL'}
예제 #8
0
def test_crop_boundless_masked(bounds):
    raster_w_mask = GeoRaster2.open("tests/data/raster/rgb.tif")
    raster_wo_mask = GeoRaster2.open("tests/data/raster/rgb.jp2")

    roi = GeoVector(Polygon.from_bounds(*bounds), WEB_MERCATOR_CRS)
    assert (np.array_equal(
        raster_w_mask.crop(roi).image.mask,
        raster_wo_mask.crop(roi).image.mask))
예제 #9
0
def check_file(filename):
    try:
        GeoRaster2.open(filename, lazy_load=False)
    except (OSError, GeoRaster2IOError):
        logger.warning(f"Removing file {filename}")
        os.remove(filename)
    else:
        logger.info(f"File {filename} looks correct")
예제 #10
0
def test_featurecollection_apply_on_rasters_collection():
    rasters_list = [
        GeoRaster2.open("./tests/data/raster/overlap1.tif"),
        GeoRaster2.open("./tests/data/raster/overlap2.tif")
    ]
    fc = FeatureCollection.from_georasters(rasters_list)
    new_fc = fc.apply(prop1=3)
    assert new_fc.is_rasters_collection()
예제 #11
0
def test_save_preserves_nodata():
    expected_nodata = 200
    path = '/vsimem/raster_for_test.tif'
    raster_nodata = GeoRaster2(some_array,
                               nodata=expected_nodata,
                               affine=some_affine,
                               crs=some_crs)
    raster_nodata.save(path)
    assert expected_nodata == GeoRaster2.open(path).nodata_value
예제 #12
0
def test_limit_to_bands_off_memory():
    r1 = GeoRaster2.open("tests/data/raster/rgb.tif",
                         band_names=['r', 'g', 'b'],
                         lazy_load=False)
    r2 = GeoRaster2.open("tests/data/raster/rgb.tif",
                         band_names=['r', 'g', 'b'])
    assert r1.limit_to_bands(['b', 'r']) == r2.limit_to_bands(['b', 'r'])
    assert r1.limit_to_bands(['r', 'b']) != r2.limit_to_bands(['b', 'r'])
    assert r2._image is None
예제 #13
0
def test_png_thumbnail_has_expected_properties():
    raster = GeoRaster2.open("tests/data/raster/rgb.tif")
    expected_thumbnail = raster.resize(dest_width=512, resampling=Resampling.nearest)
    result_thumbnail = GeoRaster2.from_bytes(
        raster.to_png(transparent=True, thumbnail_size=512, resampling=Resampling.nearest, in_range='image'),
        affine=expected_thumbnail.affine, crs=expected_thumbnail.crs, band_names=expected_thumbnail.band_names
    )

    assert result_thumbnail == expected_thumbnail
예제 #14
0
def test_png_thumbnail_has_expected_properties():
    raster = GeoRaster2.open("tests/data/raster/rgb.tif")
    expected_thumbnail = raster.resize(dest_width=512,
                                       resampling=Resampling.nearest)
    result_thumbnail = GeoRaster2.from_bytes(
        raster._repr_png_(),
        affine=expected_thumbnail.affine,
        crs=expected_thumbnail.crs,
        band_names=expected_thumbnail.band_names)

    assert result_thumbnail == expected_thumbnail
예제 #15
0
def test_merge_all_non_overlapping_has_correct_metadata():
    # See https://github.com/satellogic/telluric/issues/65
    affine = Affine.translation(0, 2) * Affine.scale(1, -1)

    rs1 = GeoRaster2(
        image=np.array([[[100, 0], [100, 0]]], dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        band_names=['red'],
        nodata=0,
    )

    rs2 = GeoRaster2(
        image=np.array([[[110, 0], [110, 0]]], dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        band_names=['green'],
        nodata=0,
    )

    rs3 = GeoRaster2(
        image=np.array([[[0, 200], [0, 200]]], dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        band_names=['red'],
        nodata=0,
    )

    rs4 = GeoRaster2(
        image=np.array([[[0, 210], [0, 210]]], dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        band_names=['green'],
        nodata=0,
    )

    expected_metadata = GeoRaster2(image=np.ma.masked_array([[
        [0, 2],
        [0, 2],
    ], [
        [1, 3],
        [1, 3],
    ]], np.ma.nomask),
                                   affine=affine,
                                   crs=WGS84_CRS,
                                   band_names=['red', 'green'])

    metadata = merge_all([rs1, rs2, rs3, rs4],
                         rs1.footprint(),
                         pixel_strategy=PixelStrategy.INDEX)

    assert metadata == expected_metadata
예제 #16
0
def test_empty_from_roi_respects_footprint():
    # See https://github.com/satellogic/telluric/issues/39
    raster = GeoRaster2.open("tests/data/raster/overlap1.tif")

    empty = GeoRaster2.empty_from_roi(shape=raster.shape[1:][::-1], ul_corner=(v[0] for v in raster.corner('ul').xy),
                                      resolution=raster.res_xy(), crs=raster.crs,
                                      band_names=raster.band_names, dtype=raster.dtype)

    empty_simple = GeoRaster2.empty_from_roi(roi=raster.footprint(),
                                             resolution=raster.res_xy(),
                                             band_names=raster.band_names, dtype=raster.dtype)

    assert raster.footprint().almost_equals(empty.footprint())
    assert raster.footprint().almost_equals(empty_simple.footprint())
예제 #17
0
def test_read_write_internal_external_mask():
    with TemporaryDirectory() as folder:
        # internal mask (default) leaves no .msk file:
        internal_path = os.path.join(folder, 'internal.tif')
        some_raster_multiband.save(internal_path, factors=default_factors)
        assert not os.path.exists(internal_path + '.msk')

        # external mask leaves .msk file:
        external_path = os.path.join(folder, 'external.tif')
        some_raster_multiband.save(external_path, GDAL_TIFF_INTERNAL_MASK=False, factors=default_factors)
        assert os.path.exists(external_path + '.msk')

        # other than that, both rasters are identical:
        assert GeoRaster2.open(internal_path) == GeoRaster2.open(external_path)
예제 #18
0
def test_to_png_from_bytes():
    arr = np.array(
        [np.full((3, 5), 1),
         np.full((3, 5), 5),
         np.full((3, 5), 10)],
        dtype=np.uint8)
    raster = GeoRaster2(image=arr,
                        affine=Affine.identity(),
                        crs=WEB_MERCATOR_CRS,
                        band_names=['r', 'g', 'b'])
    png_bytes = raster.to_png()
    assert raster == GeoRaster2.from_bytes(png_bytes,
                                           affine=raster.affine,
                                           crs=raster.crs,
                                           band_names=raster.band_names)
예제 #19
0
def test_crop_respects_rounding_precision():
    # https://github.com/satellogic/telluric/pull/311
    r1 = GeoRaster2.open("tests/data/raster/non_aligned1.tif", lazy_load=False)
    r2 = GeoRaster2.open("tests/data/raster/non_aligned2.tif", lazy_load=False)
    roi = GeoVector.from_bounds(
        271806.0179640717,
        1438839.4164977344,
        337216.40041283204,
        1519170.2272236191,
        crs=r1.crs,
    )
    r1_cropped = r1.crop(roi)
    r2_cropped = r2.crop(roi)
    assert r1.shape == r2.shape
    assert r1_cropped.shape == r2_cropped.shape
예제 #20
0
def test_georaster_save_emits_warning_if_uneven_mask(recwarn):
    affine = Affine.translation(0, 2) * Affine.scale(1, -1)
    raster = GeoRaster2(
        image=np.array([
            [
                [100, 200],
                [100, 200]
            ],
            [
                [110, 0],
                [110, 0]
            ]
        ], dtype=np.uint8),
        affine=affine,
        crs=WGS84_CRS,
        nodata=0
    )

    orig_mask = raster.image.mask

    assert not (orig_mask == orig_mask[0]).all()

    with NamedTemporaryFile(suffix=".tif") as fp:
        raster.save(fp.name)

    w = recwarn.pop(GeoRaster2Warning)
    assert (
        "Saving different masks per band is not supported, the union of the masked values will be performed."
        in str(w.message)
    )
예제 #21
0
def test_reproject_rpcs():
    # test reprojection when rpcs are defined and input raster has no src_crs
    # TODO: add smaller test data
    raster = GeoRaster2.open("tests/data/raster/grayscale.tif")
    reprojected = raster.reproject(dst_crs=WEB_MERCATOR_CRS, rpcs=raster.rpcs)
    assert reprojected.shape == (1, 2072, 5241)
    assert reprojected.mean()[0] == pytest.approx(724.4861459505134, 1e-4)
예제 #22
0
def test_read_write():
    for extension in ['tif', 'png']:
        with TemporaryDirectory() as folder:
            path = os.path.join(folder, 'test.%s' % extension)
            some_raster_multiband.save(path, factors=default_factors)
            read = GeoRaster2.open(path)
            assert read == some_raster_multiband
예제 #23
0
def test_rasterization_of_line_simple():
    resolution = 1
    pixels_width = 1

    line = GeoFeature.from_shape(LineString([(2.5, 0), (2.5, 3)]))
    roi = GeoVector.from_bounds(xmin=0,
                                ymin=0,
                                xmax=5,
                                ymax=5,
                                crs=DEFAULT_CRS)

    fc = FeatureCollection([line])

    expected_image = np.zeros((5, 5), dtype=np.uint8)
    expected_image[2:, 2] = 1

    expected_affine = Affine(1.0, 0.0, 0.0, 0.0, -1.0, 5.0)

    expected_crs = DEFAULT_CRS

    expected_result = GeoRaster2(expected_image,
                                 expected_affine,
                                 expected_crs,
                                 nodata=0)

    result = fc.rasterize(resolution,
                          polygonize_width=pixels_width,
                          crs=DEFAULT_CRS,
                          bounds=roi)

    assert result == expected_result
예제 #24
0
def test_read_non_georeferenced():
    crs = CRS(init='epsg:3857')
    affine = Affine(10.0, 0.0, -6425941.63996855,
                    0.0, -10.0, -3169315.69478084)
    raster = GeoRaster2.open('tests/data/raster/no_georef.png', crs=crs, affine=affine, lazy_load=False)
    assert raster.crs == crs
    assert raster.affine == affine
예제 #25
0
def test_blockshapes_for_in_memory_raster():
    raster = GeoRaster2(some_image_2d,
                        affine=some_affine,
                        crs=some_crs,
                        band_names=['r'])
    assert len(raster.blockshapes) == raster.num_bands
    assert raster.blockshapes == [(raster.height, raster.width)]
예제 #26
0
def test_rasterization_of_line_has_correct_pixel_width(resolution):
    xmax, ymax = 11, 5
    pixels_width = 1

    line = GeoFeature.from_shape(
        LineString([(xmax / 2, 0), (xmax / 2, ymax * 4 / 5)]))
    roi = GeoVector.from_bounds(xmin=0,
                                ymin=0,
                                xmax=xmax,
                                ymax=ymax,
                                crs=DEFAULT_CRS)

    fc = FeatureCollection([line])

    expected_image = np.zeros(
        (int(ymax // resolution), int(xmax // resolution)), dtype=np.uint8)
    expected_image[int(1 // resolution):, expected_image.shape[1] // 2] = 1

    expected_affine = Affine(resolution, 0.0, 0.0, 0.0, -resolution, 5.0)

    expected_crs = DEFAULT_CRS

    expected_result = GeoRaster2(expected_image,
                                 expected_affine,
                                 expected_crs,
                                 nodata=0)

    result = fc.rasterize(resolution,
                          polygonize_width=pixels_width,
                          crs=DEFAULT_CRS,
                          bounds=roi)

    assert result == expected_result
예제 #27
0
def black_and_white_raster(band_names=[],
                           height=10,
                           width=10,
                           dtype=np.uint16,
                           crs=WEB_MERCATOR_CRS,
                           affine=None):
    if affine is None:
        eps = 1e-100
        affine = Affine.translation(10, 12) * Affine.scale(1, -1)
    bands_num = len(band_names)
    shape = [bands_num, height, width]
    array = np.zeros(shape, dtype=dtype)
    mask = np.full(shape, False, dtype=np.bool)
    val = 0
    for i in range(height):
        for j in range(width):
            for z in range(bands_num):
                array[z, i, j] = val
                val = 1 - val

    image = np.ma.array(data=array, mask=mask)
    raster = GeoRaster2(image=image,
                        affine=affine,
                        crs=crs,
                        band_names=band_names)
    return raster
예제 #28
0
def test_rasterization_function_user_dtype(fill_value, dtype):
    resolution = 1

    line = GeoVector.from_bounds(xmin=2, ymin=0, xmax=3, ymax=3, crs=DEFAULT_CRS)
    roi = GeoVector.from_bounds(xmin=0, ymin=0, xmax=5, ymax=5, crs=DEFAULT_CRS)

    expected_data = np.zeros((5, 5), dtype=dtype)
    expected_data[2:, 2] = fill_value
    expected_mask = np.ones((5, 5), dtype=bool)
    expected_mask[2:, 2] = False
    expected_image = np.ma.masked_array(
        expected_data,
        expected_mask
    )

    expected_affine = Affine(1.0, 0.0, 0.0, 0.0, -1.0, 5.0)

    expected_crs = DEFAULT_CRS

    expected_result = GeoRaster2(expected_image, expected_affine, expected_crs)

    result = rasterize([line.get_shape(DEFAULT_CRS)], DEFAULT_CRS, roi.get_shape(DEFAULT_CRS),
                       resolution, fill_value=fill_value, dtype=dtype)

    assert result == expected_result
예제 #29
0
def test_empty_raster_from_roi_affine_3_bands_high():
    affine = Affine.translation(10, 12) * Affine.scale(2, -2)
    raster = make_test_raster(88, [1, 3, 2], affine=affine, height=1301, width=4)
    empty = GeoRaster2.empty_from_roi(band_names=raster.band_names, roi=raster.footprint(), resolution=2)
    assert(affine.almost_equals(empty.affine))
    assert(raster.crs == empty.crs)
    assert(raster.shape == empty.shape)
예제 #30
0
def test_astype_float32_to_uint8_conversion_with_in_range():
    raster_uint8 = some_float32_raster.astype(np.uint8, in_range=(0.5, 1.0))
    expected_raster_uint8 = GeoRaster2(image=np.array([
        [[0, 0], [0, 51]],
        [[101, 153], [203, 255]]], dtype=np.uint8),
        affine=some_float32_raster.affine, crs=some_float32_raster.crs, nodata=None)
    assert raster_uint8 == expected_raster_uint8