class GeoRasterCropTest(TestCase):
    metric_affine = Affine(1, 0.0, 2653750, 0.0, -1, 4594461)
    metric_crs = CRS({'init': 'epsg:3857'})
    geographic_affine = Affine(8.03258139076081e-06, 0.0, 23.83904185232179,
                               0.0, -8.03258139076081e-06, 38.10635414334363)
    geographic_crs = CRS({'init': 'epsg:4326'})

    def metric_raster(cls):
        return GeoRaster2(np.random.uniform(0, 256, (3, 3911, 3708)),
                          affine=cls.metric_affine,
                          crs=cls.metric_crs)

    def geographic_raster(cls):
        return GeoRaster2(np.random.uniform(0, 256, (3, 4147, 4147)),
                          affine=cls.geographic_affine,
                          crs=cls.geographic_crs)

    def test_crop_in_memory_and_off_memory_without_resizing_are_the_same(self):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster2 = GeoRaster2.open(rf.name)
            off_memory_crop = raster2.crop(shape)
            # load the image data
            raster2.image
            in_memory_crop = raster2.crop(shape)
            self.assertEqual(off_memory_crop, in_memory_crop)

    @window_data
    def test_crop_and_get_tile_do_the_same(self):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster2 = GeoRaster2.open(rf.name)
            tile15 = raster2.get_tile(*tiles[15])
            # load the image data
            raster2.image
            cropped15 = raster2.crop(shape, MERCATOR_RESOLUTION_MAPPING[15])
            self.assertEqual(tile15, cropped15)

    @window_data
    def test_crop_and_get_tile_do_the_same_when_image_is_populated(self):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster = GeoRaster2.open(rf.name)
            tile15 = raster.get_tile(*tiles[15])
            raster._populate_from_rasterio_object(read_image=True)
            cropped_15 = raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[15])
            self.assertEqual(tile15, cropped_15)

    @window_data
    def test_crop_image_from_and_get_win_do_the_same_with_resize(self):
        bounds = (2, 3, 4, 5)
        win = rasterio.windows.Window(bounds[0], bounds[1],
                                      bounds[2] - bounds[0],
                                      bounds[3] - bounds[1])
        xsize = round((bounds[2] - bounds[0]) / 2)
        ysize = round((bounds[3] - bounds[1]) / 2)
        raster = self.metric_raster()

        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster.save('area.tif', tags={'AREA_OR_POINT': 'Area'})
            raster.save('point.tif', tags={'AREA_OR_POINT': 'Point'})
            saved_raster = GeoRaster2.open(rf.name)
            cropped_win = saved_raster.get_window(win,
                                                  xsize=xsize,
                                                  ysize=ysize)
            saved_raster_area = GeoRaster2.open('area.tif')
            cropped_win_area = saved_raster_area.get_window(win,
                                                            xsize=xsize,
                                                            ysize=ysize)
            saved_raster_point = GeoRaster2.open('point.tif')
            cropped_win_point = saved_raster_point.get_window(win,
                                                              xsize=xsize,
                                                              ysize=ysize)

        cropped_image = raster._crop(bounds, xsize=xsize, ysize=ysize)

        print('cropped_win_area pixels\n', cropped_win_area.image)
        print('cropped_win_point pixels\n', cropped_win_point.image)
        print('cropped_win pixels\n', cropped_win.image)
        print('cropped_image pixels\n', cropped_image.image)
        if (cropped_win_point == cropped_win_area):
            print('point == area')
        if (cropped_image == cropped_win_area):
            print('image == area')
        if (cropped_image == cropped_win_point):
            print('image == point')
        if (cropped_win == cropped_win_area):
            print('win == area')
        if (cropped_win == cropped_win_point):
            print('win == point')

        self.assertEqual(cropped_image, cropped_win)

    @framing
    def test_crop_and_get_tile_do_the_same_when_image_is_populated_first_high_zoom(
            self):
        coords = mercantile.xy_bounds(*tiles[17])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster = GeoRaster2.open(rf.name)
            raster._populate_from_rasterio_object(read_image=True)
            tile17 = raster.get_tile(*tiles[17])
            cropped_17 = raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[17])
            self.assertEqual(tile17, cropped_17)

    @framing
    def test_crop_and_get_tile_do_the_same_when_image_is_populated_first_mid_zoom(
            self):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster = GeoRaster2.open(rf.name)
            raster._populate_from_rasterio_object(read_image=True)
            tile15 = raster.get_tile(*tiles[15])
            cropped_15 = raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[15])
            self.assertEqual(tile15, cropped_15)

    @framing
    def test_crop_and_get_tile_do_the_same_when_image_is_populated_first_for_low_zoom(
            self):
        coords = mercantile.xy_bounds(*tiles[11])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster = GeoRaster2.open(rf.name)
            raster._populate_from_rasterio_object(read_image=True)
            tile11 = raster.get_tile(*tiles[11])
            cropped_11 = raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[11])
            self.assertEqual(tile11, cropped_11)

    def test_crop_image_from_and_get_win_do_the_same_full_resolution(self):
        bounds = (200, 130, 400, 150)
        win = rasterio.windows.Window(bounds[0], bounds[1],
                                      bounds[2] - bounds[0],
                                      bounds[3] - bounds[1])
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            saved_raster = GeoRaster2.open(rf.name)
            cropped_win = saved_raster.get_window(win)
        cropped_image = raster._crop(bounds)
        self.assertEqual(cropped_image, cropped_win)

    @patch.object(GeoRaster2, '_crop')
    def test_crop_use_crop_image_for_a_loaded_image(self, mock__crop):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[15])
        assert mock__crop.called_once

    @patch.object(GeoRaster2, 'get_window')
    def test_crop_use_get_window_for_a_not_loaded_image(self, mock_get_window):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        with NamedTemporaryFile(mode='w+b', suffix=".tif") as rf:
            raster.save(rf.name)
            raster = GeoRaster2.open(rf.name)
            raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[15])
            assert mock_get_window.called_once

    def test_crop_returns_full_resolution_as_default(self):
        coords = mercantile.xy_bounds(*tiles[17])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        _, win = raster._vector_to_raster_bounds(shape)
        cropped = raster.crop(shape)
        self.assertEqual(
            cropped.shape,
            (raster.num_bands, round(win.height), round(win.width)))
        self.assertEqual(cropped.affine[0], raster.affine[0])

    def test_memory_crop_returns_resized_resolution(self):
        coords = mercantile.xy_bounds(*tiles[15])
        shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
        raster = self.metric_raster()
        cropped = raster.crop(shape, MERCATOR_RESOLUTION_MAPPING[15])
        self.assertEqual(cropped.shape, (raster.num_bands, 256, 256))
        self.assertAlmostEqual(cropped.affine[0],
                               MERCATOR_RESOLUTION_MAPPING[15], 2)

    def test_geographic_crop(self):
        raster = self.geographic_raster()
        rhombus_on_image = Polygon([[0, 2], [1, 1], [2, 2], [1,
                                                             3]])  # in pixels
        rhombus_world = raster.to_world(rhombus_on_image)
        cropped = raster.crop(rhombus_world)
        r = raster[0:2, 1:3]
        assert cropped == r

    def test_geographic_crop_with_resize(self):
        coords = mercantile.xy_bounds(*tiles[17])
        raster = self.geographic_raster()
        vector = GeoVector(Polygon.from_bounds(*coords), crs=self.metric_crs)
        x_ex_res, y_ex_res = convert_resolution_from_meters_to_deg(
            self.metric_affine[6], MERCATOR_RESOLUTION_MAPPING[17])
        cropped = raster.crop(vector, (x_ex_res, y_ex_res))
        self.assertAlmostEqual(cropped.affine[0], x_ex_res)
        self.assertAlmostEqual(abs(cropped.affine[4]), y_ex_res, 6)

    def test_crop_raises_error_for_impossible_transformation(self):
        raster = self.metric_raster()
        vector = GeoVector(Polygon.from_bounds(-180, -90, 180, 90),
                           crs=self.geographic_crs)
        with self.assertRaises(GeoRaster2Error):
            raster.crop(vector)

    def test_crop_of_rasters_with_opposite_affine_and_data_return_the_same(
            self):
        array = np.arange(0, 20).reshape(1, 4, 5)
        array2 = np.arange(19, -1, -1).reshape(1, 4, 5)
        array2.sort()

        image1 = np.ma.array(array, mask=False)
        image2 = np.ma.array(array2, mask=False)

        aff2 = Affine.translation(0, -8) * Affine.scale(2, 2)
        aff = Affine.scale(2, -2)

        r1 = GeoRaster2(image=image1, affine=aff, crs=WEB_MERCATOR_CRS)
        r2 = GeoRaster2(image=image2, affine=aff2, crs=WEB_MERCATOR_CRS)

        # r1 == r2  # doesn't work, see https://github.com/satellogic/telluric/issues/79
        roi = GeoVector(Polygon.from_bounds(0, 0, 3, -3), crs=WEB_MERCATOR_CRS)

        r1c = r1.crop(roi)
        r2c = r2.crop(roi)

        # r1c == r2c  # doesn't work, see https://github.com/satellogic/telluric/issues/79
        # currently this is the only way to test the result is the same
        assert r2c.to_png() == r1c.to_png()
Exemple #2
0
def test_empty_crs_str():
    """str(CRS()) should be empty string"""
    assert str(CRS()) == ''
Exemple #3
0
def test_crs_constructor_keywords():
    """Can create a CRS from keyword args, ignoring unknowns"""
    crs = CRS(init='epsg:3857', foo='bar')
    assert crs['init'] == 'epsg:3857'
    assert 'PROJCS["WGS 84 / Pseudo-Mercator"' in crs.wkt
Exemple #4
0
def test_crs_OSR_equivalence():
    crs1 = CRS.from_string('+proj=longlat +datum=WGS84 +no_defs')
    crs2 = CRS.from_string('+proj=latlong +datum=WGS84 +no_defs')
    crs3 = CRS({'init': 'epsg:4326'})
    assert crs1 == crs2
    assert crs1 == crs3
Exemple #5
0
def test_environ_patch(gdalenv, monkeypatch):
    """PROJ_LIB is patched when rasterio._crs is imported"""
    monkeypatch.delenv('GDAL_DATA', raising=False)
    monkeypatch.delenv('PROJ_LIB', raising=False)
    with env_ctx_if_needed():
        assert CRS.from_epsg(4326) != CRS(units='m', proj='aeqd', ellps='WGS84', datum='WGS84', lat_0=-17.0, lon_0=-44.0)
Exemple #6
0
def test_repr():
    assert repr(CRS({'init': 'epsg:4326'})).startswith("CRS.from_epsg(4326)")
Exemple #7
0
def test_epsg_code_true():
    assert CRS({'init': 'epsg:4326'}).is_epsg_code
Exemple #8
0
def test_is_valid_false():
    with pytest.raises(CRSError):
        CRS(init='EPSG:432600').is_valid
Exemple #9
0
def test_is_valid():
    assert CRS(init='EPSG:4326').is_valid
Exemple #10
0
import pandas as pd
import rasterio
from rasterio.crs import CRS
from rasterio.features import rasterize, shapes
from rasterio.transform import from_origin
from rasterio.warp import Resampling, reproject, transform_geom
from scipy.ndimage import binary_closing, uniform_filter
from shapely.geometry import Polygon, shape
from skimage.morphology import label
from sklearn.metrics import (f1_score, precision_score, recall_score,
                             roc_auc_score)

from config import DATA_DIR, DB_NAME, DB_USER, DB_PASS, DB_HOST, YEARS
from maupp import CaseStudy, osm, reference, srtm

WGS84 = CRS(init='EPSG:4326')


def available(case_study):
    """List available results for a given case study."""
    years_available = []
    filenames = []
    for year in YEARS:
        path = os.path.join(case_study.outputdir,
                            str(year), 'probabilities.tif')
        if os.path.isfile(path):
            years_available.append(year)
            filenames.append(path)
    return filenames, years_available

Exemple #11
0
def test_to_string():
    assert CRS({'init': 'EPSG:4326'}).to_string() == "+init=EPSG:4326"
Exemple #12
0
def project_coords(x, y, src_crs, dst_crs, return_as='1d', **kwargs):
    """
    Projects coordinates to a new CRS

    Args:
        x (1d array-like): The x coordinates.
        y (1d array-like): The y coordinates.
        src_crs (str, dict, object): The source CRS.
        dst_crs (str, dict, object): The destination CRS.
        return_as (Optional[str]): How to return the coordinates. Choices are ['1d', '2d'].
        kwargs (Optional[dict]): Keyword arguments passed to ``rasterio.warp.reproject``.

    Returns:
        ``numpy.array``, ``numpy.array`` or ``xr.DataArray``
    """

    if return_as == '1d':

        df_tmp = gpd.GeoDataFrame(np.arange(0, x.shape[0]),
                                  geometry=gpd.points_from_xy(x, y),
                                  crs=src_crs)

        df_tmp = df_tmp.to_crs(dst_crs)

        return df_tmp.geometry.x.values, df_tmp.geometry.y.values

    else:

        if not isinstance(x, np.ndarray):
            x = np.array(x, dtype='float64')

        if not isinstance(y, np.ndarray):
            y = np.array(y, dtype='float64')

        yy = np.meshgrid(x, y)[1]

        latitudes = np.zeros(yy.shape, dtype='float64')

        src_transform = from_bounds(x[0], y[-1], x[-1], y[0],
                                    latitudes.shape[1], latitudes.shape[0])

        west, south, east, north = transform_bounds(src_crs, CRS(dst_crs),
                                                    x[0], y[-1], x[-1], y[0])
        dst_transform = from_bounds(west, south, east, north,
                                    latitudes.shape[1], latitudes.shape[0])

        latitudes = reproject(yy,
                              destination=latitudes,
                              src_transform=src_transform,
                              dst_transform=dst_transform,
                              src_crs=CRS.from_epsg(src_crs.split(':')[1]),
                              dst_crs=CRS(dst_crs),
                              **kwargs)[0]

        return xr.DataArray(data=da.from_array(latitudes[np.newaxis, :, :],
                                               chunks=(1, 512, 512)),
                            dims=('band', 'y', 'x'),
                            coords={
                                'band': ['lat'],
                                'y': ('y', latitudes[:, 0]),
                                'x': ('x', np.arange(1,
                                                     latitudes.shape[1] + 1))
                            })
Exemple #13
0
import os
import rasterio
from rasterio.crs import CRS

assert "GDAL_DATA" not in os.environ

azeq_point = CRS({
    "units": "m",
    "proj": "aeqd",
    "ellps": "WGS84",
    "datum": "WGS84",
    "lat_0": -17.0,
    "lon_0": -44.0,
})

with rasterio.Env():
    assert azeq_point == azeq_point
    wgs84 = CRS.from_epsg(4326)
    assert not azeq_point == wgs84

assert azeq_point == azeq_point
wgs84 = CRS.from_epsg(4326)
assert not azeq_point == wgs84  # Cached
Exemple #14
0
def main():

    parser = argparse.ArgumentParser()
    add_local_args(parser)
    args = parser.parse_args()

    # TODO we can probably get rid of this
    first = rasterio.open(args.inputs[0])

    sources = []
    for fname in args.inputs:
        sources.append(Dataset(fname))

    lat, lng = [], []
    for src in sources:
        lng.extend(src.variables['longitude'][:].tolist())
        lat.extend(src.variables['latitude'][:].tolist())
    lng = list(sorted(set(lng)))
    lat = list(sorted(set(lat)))

    dst_w, dst_s, dst_e, dst_n = min(lng), min(lat), max(lng), max(lat)

    # TODO is this safe?
    #  creating a set from floats seems dangerous
    output_width = len(lng)
    output_height = len(lat)
    # frequent off-by-one errors
    #output_width = int(math.ceil((dst_e - dst_w) / first.res[0])+1)
    #output_height = int(math.ceil((dst_n - dst_s) / first.res[1])+1)

    log.debug("Output bounds: %r", (dst_w, dst_s, dst_e, dst_n))
    output_transform = Affine.translation(dst_w, dst_n)
    log.debug("Output transform, before scaling: %r", output_transform)
    output_transform *= Affine.scale(first.res[0], -first.res[1])
    # TODO the following line is close. check parameter order
    #output_transform *= Affine.scale(lat[1]-lat[0], lng[1]-lng[0])
    log.debug("Output transform, after scaling: %r", output_transform)

    # Seems close
    #output_width = int(math.ceil((dst_e - dst_w) / first.res[0])+1)
    #output_height = int(math.ceil((dst_n - dst_s) / first.res[1])+1)

    # Adjust bounds to fit.
    dst_e, dst_s = output_transform * (output_width, output_height)
    log.debug("Output width: %d, height: %d", output_width, output_height)
    log.debug("Adjusted bounds: %r", (dst_w, dst_s, dst_e, dst_n))

    profile = first.profile
    profile['driver'] = 'GTiff'
    profile['transform'] = output_transform
    profile['height'] = output_height
    profile['width'] = output_width
    profile['crs'] = CRS().from_string(sources[0].crs)

    profile['nodata'] = first.nodata

    band = np.zeros((profile['height'], profile['width']),
                    dtype=first.dtypes[0])

    if not args.separate:
        with rasterio.open(args.output, 'w', **profile) as dstrast:
            for i in range(dstrast.count):
                if not args.quiet and i % 10 == 0:
                    sys.stderr.write('.')
                for src in sources:
                    b = src.variables[args.varname][i, :, :]
                    off_y = src.variables['latitude'][:].max()
                    off_x = src.variables['longitude'][:].min()
                    rowcol = dstrast.index(off_x, off_y)
                    row, col = int(rowcol[0]), int(rowcol[1])
                    log.debug('upper-left: lat=%3.6f (%d), long=%3.6f (%d)',
                              off_y, row, off_x, col)
                    band[row:row + b.shape[0], col:col + b.shape[1]] = b
                    dstrast.write(band, i + 1)

    if args.separate:
        timedim = sources[0].variables[args.timedim]
        #nodata=sources[0].variables[args.varname].missing_value)
        profile.update(count=1, blockxsize=256, blockysize=256, tiled='yes')
        del profile['crs']
        for i in range(len(timedim)):
            if not args.quiet and i % 10 == 0:
                sys.stderr.write('.')
            filename, ext = os.path.splitext(args.output)
            output = '%s_%04d%s' % (filename, int(timedim[i]), ext)
            with rasterio.open(output, 'w', **profile) as dstrast:
                for src in sources:
                    b = src.variables[args.varname][i, :, :]
                    off_y = src.variables['latitude'][:].max()
                    off_x = src.variables['longitude'][:].min()
                    rowcol = dstrast.index(off_x, off_y)
                    row, col = int(rowcol[0]), int(rowcol[1])
                    log.debug('upper-left: lat=%3.6f (%d), long=%3.6f (%d)',
                              off_y, row, off_x, col)
                    band[row:row + b.shape[0], col:col + b.shape[1]] = b
                    dstrast.write(band, 1)

    sys.stderr.write('done\n')
Exemple #15
0
def test_is_valid():
    assert CRS(init='epsg:4326').is_valid
Exemple #16
0
def test_repr():
    assert repr(CRS({'init': 'EPSG:4326'})).startswith("CRS({'init'")
Exemple #17
0
def test_has_wkt_property():
    assert CRS({'init': 'epsg:4326'}).wkt.startswith('GEOGCS["WGS 84",DATUM')
Exemple #18
0
def test_epsg_code():
    assert CRS({'init': 'EPSG:4326'}).is_epsg_code
    assert not CRS({'proj': 'latlon'}).is_epsg_code
Exemple #19
0
def test_dunder_str():
    assert str(CRS({'init': 'epsg:4326'})) == CRS({'init': 'epsg:4326'}).to_string()
Exemple #20
0
def test_is_geographic(proj, expected):
    assert CRS(proj).is_geographic is expected
Exemple #21
0
def test_epsg():
    assert CRS({'init': 'epsg:4326'}).to_epsg() == 4326
    assert CRS.from_string('+proj=longlat +datum=WGS84 +no_defs').to_epsg() == 4326
Exemple #22
0
def test_null_crs_equality():
    assert CRS() == CRS()
    a = CRS()
    assert a == a
    assert not a != a
Exemple #23
0
def test_to_esri_wkt_fix_datum():
    """Morph to Esri form"""
    assert 'DATUM["D_North_American_1983"' in CRS(init='epsg:26913').to_wkt(morph_to_esri_dialect=True)
Exemple #24
0
def test_null_and_valid_crs_equality():
    assert (CRS() == CRS(init='epsg:4326')) is False
Exemple #25
0
def test_capitalized_epsg_init():
    """Ensure that old behavior is preserved"""
    assert CRS(init='EPSG:4326').to_epsg() == 4326
Exemple #26
0
def test_to_string():
    assert CRS({'init': 'epsg:4326'}).to_string() == "EPSG:4326"
Exemple #27
0
def test_crs_constructor_dict():
    """Can create a CRS from a dict"""
    crs = CRS({'init': 'epsg:3857'})
    assert crs['init'] == 'epsg:3857'
    assert 'PROJCS["WGS 84 / Pseudo-Mercator"' in crs.wkt
Exemple #28
0
def test_is_valid_false():
    with Env(), pytest.raises(CRSError):
        CRS(init='epsg:432600').is_valid
Exemple #29
0
def test_crs_constructor_crs_obj():
    """Can create a CRS from a CRS obj"""
    crs = CRS(CRS(init='epsg:3857'))
    assert crs['init'] == 'epsg:3857'
    assert 'PROJCS["WGS 84 / Pseudo-Mercator"' in crs.wkt
 def test_geo_bounding_tile(self):
     gr = self.raster_for_test()
     gv = gr.footprint().reproject(CRS({'init': 'epsg:4326'}))
     bounding_tile = mercantile.bounding_tile(*gv.get_shape(gv.crs).bounds)
     self.assertEqual(bounding_tile, (2319, 1578, 12))