Пример #1
0
def test_xy_bounds(args):
    expected = (-1017529.7205322663, 7005300.768279833,
                -978393.962050256, 7044436.526761846)
    bounds = mercantile.xy_bounds(*args)

    for a, b in zip(expected, bounds):
        assert round(a - b, 7) == 0
Пример #2
0
def tile(address,
         tile_x,
         tile_y,
         tile_z,
         rgb=None,
         tilesize=256,
         nodata=None,
         alpha=None):
    """Create mercator tile from any images.

    Attributes
    ----------

    address : str
        file url.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, int, optional (default: (1, 2, 3))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    nodata: int or float, optional (defaults: None)
    alpha: int, optional (defaults: None)
        Force alphaband if not present in the dataset metadata

    Returns
    -------
    data : numpy ndarray
    mask: numpy array
    """

    with rasterio.open(address) as src:
        wgs_bounds = transform_bounds(*[src.crs, 'epsg:4326'] +
                                      list(src.bounds),
                                      densify_pts=21)
        nodata = nodata if nodata is not None else src.nodata
        if not rgb:
            rgb = src.indexes

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds('Tile {}/{}/{} is outside image bounds'.format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)
    return utils.tile_band_worker(address,
                                  tile_bounds,
                                  tilesize,
                                  indexes=rgb,
                                  nodata=nodata,
                                  alpha=alpha)
Пример #3
0
        def worker(path):

            raster = rasterio_open(path)
            w, s, e, n = transform_bounds(raster.crs, "EPSG:4326", *raster.bounds)
            transform, _, _ = calculate_default_transform(raster.crs, "EPSG:3857", raster.width, raster.height, w, s, e, n)
            tiles = [mercantile.Tile(x=x, y=y, z=z) for x, y, z in mercantile.tiles(w, s, e, n, args.zoom)]
            tiled = []

            for tile in tiles:

                try:
                    w, s, e, n = mercantile.xy_bounds(tile)

                    # inspired by rio-tiler, cf: https://github.com/mapbox/rio-tiler/pull/45
                    warp_vrt = WarpedVRT(
                        raster,
                        crs="epsg:3857",
                        resampling=Resampling.bilinear,
                        add_alpha=False,
                        transform=from_bounds(w, s, e, n, args.ts, args.ts),
                        width=math.ceil((e - w) / transform.a),
                        height=math.ceil((s - n) / transform.e),
                    )
                    data = warp_vrt.read(
                        out_shape=(len(raster.indexes), args.ts, args.ts), window=warp_vrt.window(w, s, e, n)
                    )
                    image = np.moveaxis(data, 0, 2)  # C,H,W -> H,W,C
                except:
                    sys.exit("Error: Unable to tile {} from raster {}.".format(str(tile), raster))

                tile_key = (str(tile.x), str(tile.y), str(tile.z))
                if not args.label and len(tiles_map[tile_key]) == 1 and is_border(image):
                    progress.update()
                    continue

                if len(tiles_map[tile_key]) > 1:
                    out = os.path.join(splits_path, str(tiles_map[tile_key].index(path)))
                else:
                    out = args.out

                x, y, z = map(int, tile)

                if not args.label:
                    ret = tile_image_to_file(out, mercantile.Tile(x=x, y=y, z=z), image)
                if args.label:
                    ret = tile_label_to_file(out, mercantile.Tile(x=x, y=y, z=z), palette, image)

                if not ret:
                    sys.exit("Error: Unable to write tile {} from raster {}.".format(str(tile), raster))

                if len(tiles_map[tile_key]) == 1:
                    progress.update()
                    tiled.append(mercantile.Tile(x=x, y=y, z=z))

            return tiled
Пример #4
0
def test_xy_bounds(args):
    expected = (
        -1017529.7205322663,
        7005300.768279833,
        -978393.962050256,
        7044436.526761846,
    )
    bounds = mercantile.xy_bounds(*args)

    for a, b in zip(expected, bounds):
        assert round(a - b, 7) == 0
Пример #5
0
def test_tile_read_extmask():
    """Read masked area."""
    # non-boundless tile covering the masked part
    mercator_tile = mercantile.Tile(x=876431, y=1603669, z=22)
    bounds = mercantile.xy_bounds(mercator_tile)
    with rasterio.Env(GDAL_DISABLE_READDIR_ON_OPEN="TRUE"):
        with rasterio.open(S3_EXTMASK_PATH) as src_dst:
            arr, mask = reader.part(src_dst, bounds, 256, 256)
        assert arr.shape == (3, 256, 256)
        assert mask.shape == (256, 256)
        assert not mask.all()

    # boundless tile covering the masked part
    mercator_tile = mercantile.Tile(x=876431, y=1603668, z=22)
    bounds = mercantile.xy_bounds(mercator_tile)
    with rasterio.Env(GDAL_DISABLE_READDIR_ON_OPEN="EMPTY_DIR"):
        with rasterio.open(S3_MASK_PATH) as src_dst:
            arr, mask = reader.part(src_dst, bounds, 256, 256)
        assert arr.shape == (3, 256, 256)
        assert not mask.all()
Пример #6
0
    def __init__(self, access_token=os.environ.get("DG_MAPS_API_TOKEN"),
                 url="https://api.mapbox.com/v4/digitalglobe.nal0g75k/{z}/{x}/{y}.png",
                 zoom=22, bounds=None):
        self.zoom_level = zoom
        self._token = access_token
        self._name = "image-{}".format(str(uuid.uuid4()))
        self._url_template = url + "?access_token={token}"

        _first_tile = mercantile.Tile(z=self.zoom_level, x=0, y=0)
        _last_tile = mercantile.Tile(z=self.zoom_level, x=180, y=-85.05)
        g = box(*mercantile.xy_bounds(_first_tile)).union(box(*mercantile.xy_bounds(_last_tile)))

        self._full_bounds = g.bounds

        # TODO: populate rest of fields automatically
        self._tile_size = 256
        self._nbands = 3
        self._dtype = "uint8"
        self.bounds = self._expand_bounds(bounds)
        self._chunks = tuple([self._nbands] + [self._tile_size, self._tile_size])
Пример #7
0
 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.read_only_virtual_geo_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)
Пример #8
0
def geotiff_options(
    tile_x,
    tile_y,
    tile_z,
    tilesize: int = 256,
    dst_crs: CRS = CRS.from_epsg(3857)) -> Dict:
    """GeoTIFF options."""
    bounds = mercantile.xy_bounds(mercantile.Tile(x=tile_x, y=tile_y,
                                                  z=tile_z))
    dst_transform = from_bounds(*bounds, tilesize, tilesize)
    return dict(crs=dst_crs, transform=dst_transform)
Пример #9
0
 def read_tile(self, z, x, y):
     """Read raster tile data and mask."""
     mercator_tile = mercantile.Tile(x=x, y=y, z=z)
     tile_bounds = mercantile.xy_bounds(mercator_tile)
     return tile_read(
         self.path,
         tile_bounds,
         self.tiles_size,
         indexes=self.indexes,
         nodata=self.nodata,
     )
Пример #10
0
    def __init__(self, extent, map_dir, map_zoom=(MIN_ZOOM, MAX_ZOOM)):
        self._map_dir = map_dir
        self._min_zoom = map_zoom[0]
        self._max_zoom = map_zoom[1]

        # We need a manager to share the list of database names between processes
        self._manager = multiprocessing.Manager()
        self._database_names = self._manager.list()

        # Get whole tiles that span the image's extent
        self._tiles = list(mercantile.tiles(*extent, self._max_zoom))
        tile_0 = self._tiles[0]
        tile_N = self._tiles[-1]
        self._tile_start_coords = (tile_0.x, tile_0.y)
        self._tile_end_coords = (tile_N.x, tile_N.y)

        # Tiled area in world coordinates (metres)
        bounds_0 = mercantile.xy_bounds(tile_0)
        bounds_N = mercantile.xy_bounds(tile_N)
        tile_world = Rect(bounds_0.left, bounds_0.top, bounds_N.right,
                          bounds_N.bottom)

        # Tiled area in tile pixel coordinates
        tile_extent = Rect(0, 0, TILE_SIZE[0] * (tile_N.x - tile_0.x + 1),
                           TILE_SIZE[1] * (tile_N.y - tile_0.y + 1))

        # Affine transform from world to tile pixel coordinates
        sx = tile_extent.width / tile_world.width
        sy = tile_extent.height / tile_world.height
        world_to_tile = Affine((sx, -sy), (tile_world.x0, tile_world.y0),
                               (0, 0))

        # Extent in world coordinates (metres)
        sw = mercantile.xy(*extent[:2])
        ne = mercantile.xy(*extent[2:])

        # Converted to tile pixel coordinates
        self._image_rect = Rect(world_to_tile.transform(sw[0], ne[1]),
                                world_to_tile.transform(ne[0], sw[1]))

        self._processes = []
Пример #11
0
def geojson_tile_burn(tile, features, tile_size, burn_value=1, epsg=4326):
    """Burn tile with GeoJSON features."""

    shapes = ((geometry, burn_value) for feature in features
              for geometry in geojson_to_mercator(feature, epsg))

    bounds = mercantile.xy_bounds(tile)
    transform = from_bounds(*bounds, tile_size, tile_size)

    return rasterize(shapes,
                     out_shape=(tile_size, tile_size),
                     transform=transform)
Пример #12
0
 def read_val_at_pixel(self, grid, lat, lon, zoom):
     """Interpolate the row/column of a webtile from a lat/lon/zoom and extract
     the corresponding value from `grid`."""
     tile = mercantile.tile(lon, lat, zoom)
     size = len(grid)
     box = mercantile.xy_bounds(tile)
     x, y = mercantile.xy(lon, lat)
     width = box.right - box.left
     height = box.top - box.bottom
     i = int(round(size * (box.top - y) / height))
     j = int(round(size * (x - box.left) / width))
     return grid[i][j]
Пример #13
0
 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_zoom_to_resolution[11])
         self.assertEqual(tile11, cropped_11)
Пример #14
0
 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_zoom_to_resolution[15])
         self.assertEqual(tile15, cropped15)
Пример #15
0
def tile(bucket, key, tile_x, tile_y, tile_z, rgb=(1, 2, 3),  tilesize=256,
         prefix='s3:/'):
    """Create mercator tile from AWS hosted images and encodes it in base64.

    Attributes
    ----------

    bucket : str
        AWS bucket's name.
    key : str
        AWS file's key.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    tileformat : str
        Image format to return (Accepted: "jpg" or "png")
    rgb : tuple, int, optional (default: (1, 2, 3))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    out : numpy ndarray
    """

    source_address = '{}/{}/{}'.format(prefix, bucket, key)

    with rasterio.open(source_address) as src:
        wgs_bounds = transform_bounds(
            *[src.crs, 'epsg:4326'] + list(src.bounds), densify_pts=21)
        nodata = src.nodata

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds(
            'Tile {}/{}/{} is outside image bounds'.format(
                tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    w, s, e, n = tile_bounds

    out = utils.tile_band_worker(source_address,
                                 tile_bounds,
                                 tilesize,
                                 indexes=rgb,
                                 nodata=nodata)

    return out
Пример #16
0
    def _download_image(self):
        """
        return glued tiles as PIL image
        :param west: west longitude in degrees
        :param south: south latitude in degrees
        :param east: east longitude in degrees
        :param north: north latitude in degrees
        :param zoom: wanted size
        :return: Image
        """
        tiles = list(
            mercantile.tiles(self._west, self._south, self._east, self._north,
                             self.zoom))

        min_x = min_y = max_x = max_y = None

        for tile in tiles:
            min_x = min(min_x, tile.x) if min_x is not None else tile.x
            min_y = min(min_y, tile.y) if min_y is not None else tile.y
            max_x = max(max_x, tile.x) if max_x is not None else tile.x
            max_y = max(max_y, tile.y) if max_y is not None else tile.y

        out_img = PIL.Image.new('RGB', ((max_x - min_x + 1) * self.TILE_SIZE,
                                        (max_y - min_y + 1) * self.TILE_SIZE))

        pool = multiprocessing.Pool(self.pool_workers)
        results = pool.map(self._download_tile, tiles)
        pool.close()
        pool.join()

        for img, tile in results:
            left = tile.x - min_x
            top = tile.y - min_y
            bounds = (left * self.TILE_SIZE, top * self.TILE_SIZE,
                      (left + 1) * self.TILE_SIZE, (top + 1) * self.TILE_SIZE)
            out_img.paste(img, bounds)

        tiles_bounding = list(mercantile.xy_bounds(t) for t in tiles)
        min_mercator_lng = min(t.left for t in tiles_bounding)
        max_mercator_lng = max(t.right for t in tiles_bounding)
        min_mercator_lat = min(t.bottom for t in tiles_bounding)
        max_mercator_lat = max(t.top for t in tiles_bounding)

        kx = out_img.size[0] / (max_mercator_lng - min_mercator_lng)
        ky = out_img.size[1] / (max_mercator_lat - min_mercator_lat)

        self._image = out_img
        self._left = min_mercator_lng
        self._right = max_mercator_lng
        self._top = max_mercator_lat
        self._bottom = min_mercator_lat
        self._kx = kx
        self._ky = ky
Пример #17
0
    def test_implicitely_transform_to_base_srid(self):
        DJANGO_MAJOR = VERSION[0]
        if DJANGO_MAJOR < 3:
            # superfluous parenthesis for unknown reason
            expected_transform = "ST_Transform((ST_MAKEENVELOPE(-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244, 3857)), 4326)"
        else:
            expected_transform = "ST_Transform(ST_MAKEENVELOPE(-20037508.342789244, -20037508.342789244, 20037508.342789244, 20037508.342789244, 3857), 4326)"

        features = Feature.objects.filter(geom__intersects=MakeEnvelope(
            *mercantile.xy_bounds(0, 0, 0), 3857))

        self.assertIn(expected_transform, str(features.query))
Пример #18
0
    def get_tile(self, x, y, z, sort_by=None, desc=False, bands=None):
        """Generate mercator tile from rasters in FeatureCollection.

        Parameters
        ----------
        x: int
            x coordinate of tile
        y: int
            y coordinate of tile
        z: int
            zoom level
        sort_by: str
            attribute in feature to sort by
        desc: bool
            True for descending order, False for ascending
        bands: list
            list of indices of requested bads, default None which returns all bands

        Returns
        -------
        GeoRaster2

        """
        bb = mercantile.xy_bounds(x, y, z)
        roi = GeoVector.from_bounds(xmin=bb.left,
                                    ymin=bb.bottom,
                                    xmax=bb.right,
                                    ymax=bb.top,
                                    crs=WEB_MERCATOR_CRS)

        filtered_fc = self.filter(roi)

        def _get_tiled_feature(feature):
            return feature.get_tiled_feature(x, y, z, bands)

        with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executer:
            tiled_features = list(
                executer.map(_get_tiled_feature,
                             filtered_fc,
                             timeout=CONCURRENCY_TIMEOUT))

        # tiled_features can be sort for different merge strategies
        if sort_by is not None:
            tiled_features = sorted(tiled_features,
                                    reverse=desc,
                                    key=lambda f: f[sort_by])

        tiles = [f['tile'] for f in tiled_features]
        if tiles:
            tile = merge_all(tiles, roi)
            return tile
        else:
            return None
Пример #19
0
 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.read_only_virtual_geo_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)
Пример #20
0
 def test_crop_in_memory_and_off_memory_without_resizing_are_the_same(self):
     coords = mercantile.xy_bounds(*tiles[18])
     shape = GeoVector(Polygon.from_bounds(*coords), WEB_MERCATOR_CRS)
     raster = self.read_only_virtual_geo_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)
Пример #21
0
        def worker(path):

            raster = rasterio_open(path)
            w, s, e, n = transform_bounds(raster.crs, "EPSG:4326", *raster.bounds)
            tiles = [mercantile.Tile(x=x, y=y, z=z) for x, y, z in mercantile.tiles(w, s, e, n, args.zoom)]
            tiled = []

            for tile in tiles:

                if cover and tile not in cover:
                    continue

                w, s, e, n = mercantile.xy_bounds(tile)

                warp_vrt = WarpedVRT(
                    raster,
                    crs="epsg:3857",
                    resampling=Resampling.bilinear,
                    add_alpha=False,
                    transform=from_bounds(w, s, e, n, width, height),
                    width=width,
                    height=height,
                )
                data = warp_vrt.read(out_shape=(len(raster.indexes), width, height), window=warp_vrt.window(w, s, e, n))
                image = np.moveaxis(data, 0, 2)  # C,H,W -> H,W,C

                tile_key = (str(tile.x), str(tile.y), str(tile.z))
                if (
                    not args.label
                    and len(tiles_map[tile_key]) == 1
                    and is_nodata(image, args.nodata, args.nodata_threshold, args.keep_borders)
                ):
                    progress.update()
                    continue

                if len(tiles_map[tile_key]) > 1:
                    out = os.path.join(splits_path, str(tiles_map[tile_key].index(path)))
                else:
                    out = args.out

                x, y, z = map(int, tile)

                if not args.label:
                    tile_image_to_file(out, mercantile.Tile(x=x, y=y, z=z), image)
                if args.label:
                    tile_label_to_file(out, mercantile.Tile(x=x, y=y, z=z), palette, image)

                if len(tiles_map[tile_key]) == 1:
                    progress.update()
                    tiled.append(mercantile.Tile(x=x, y=y, z=z))

            return tiled
Пример #22
0
def tile(address,
         tile_x,
         tile_y,
         tile_z,
         indexes=None,
         tilesize=256,
         nodata=None):
    """
    Create mercator tile from any images.

    Attributes
    ----------
    address : str
        file url.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    indexes : tuple, int, optional (default: (1, 2, 3))
        Bands indexes for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    nodata: int or float, optional
        Overwrite nodata value for mask creation.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array

    """
    with rasterio.open(address) as src:
        wgs_bounds = transform_bounds(*[src.crs, 'epsg:4326'] +
                                      list(src.bounds),
                                      densify_pts=21)

        indexes = indexes if indexes is not None else src.indexes

        if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
            raise TileOutsideBounds(
                'Tile {}/{}/{} is outside image bounds'.format(
                    tile_z, tile_x, tile_y))

        mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
        tile_bounds = mercantile.xy_bounds(mercator_tile)
        return utils.tile_read(src,
                               tile_bounds,
                               tilesize,
                               indexes=indexes,
                               nodata=nodata)
Пример #23
0
def tile(
    src_dst: Union[DatasetReader, DatasetWriter, WarpedVRT],
    x: int,
    y: int,
    z: int,
    tilesize: int = 256,
    **kwargs,
) -> Tuple[numpy.ndarray, numpy.ndarray]:
    """
    Read mercator tile from an image.

    Attributes
    ----------
        src_dst : rasterio.io.DatasetReader
            rasterio.io.DatasetReader object
        x : int
            Mercator tile X index.
        y : int
            Mercator tile Y index.
        z : int
            Mercator tile ZOOM level.
        tilesize : int, optional
            Output tile size. Default is 256.
        kwargs : Any, optional
            Additional options to forward to part()

    Returns
    -------
        data : numpy ndarray
        mask: numpy array

    """
    warnings.warn(
        "'rio_tiler.reader.tile' will be deprecated in rio-tiler 2.0",
        DeprecationWarning,
    )

    bounds = transform_bounds(
        src_dst.crs, constants.WGS84_CRS, *src_dst.bounds, densify_pts=21
    )
    if not tile_exists(bounds, z, x, y):
        raise TileOutsideBounds(f"Tile {z}/{x}/{y} is outside image bounds")

    tile_bounds = mercantile.xy_bounds(mercantile.Tile(x=x, y=y, z=z))
    return part(
        src_dst,
        tile_bounds,
        tilesize,
        tilesize,
        dst_crs=constants.WEB_MERCATOR_CRS,
        **kwargs,
    )
Пример #24
0
def geojson_tile_burn(tile, features, srid, ts, burn_value=1):
    """Burn tile with GeoJSON features."""

    shapes = ((geometry, burn_value) for feature in features
              for geometry in geojson_reproject(feature, srid, 3857))

    bounds = mercantile.xy_bounds(tile)
    transform = from_bounds(*bounds, ts, ts)

    try:
        return rasterize(shapes, out_shape=(ts, ts), transform=transform)
    except:
        return None
Пример #25
0
def upstream_sources_for_tile(tile, catalog, min_zoom=None, max_zoom=None):
    """Render a tile's source footprints."""
    bounds = Bounds(mercantile.xy_bounds(tile), WEB_MERCATOR_CRS)
    shape = (512, 512)
    resolution = get_resolution_in_meters(bounds, shape)

    return catalog.get_sources(
        bounds,
        resolution,
        min_zoom=min_zoom,
        max_zoom=max_zoom,
        include_geometries=True,
    )
Пример #26
0
def tile(sceneid, tile_x, tile_y, tile_z, rgb=(7, 6, 5), tilesize=256):
    """Create mercator tile from CBERS data.

    Attributes
    ----------

    sceneid : str
        CBERS sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    rgb : tuple, int, optional (default: ('5', '6', '7'))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.

    Returns
    -------
    data : numpy ndarray
    mask: numpy array
    """

    if not isinstance(rgb, tuple):
        rgb = tuple((rgb, ))

    scene_params = utils.cbers_parse_scene_id(sceneid)
    cbers_address = '{}/{}'.format(CBERS_BUCKET, scene_params['key'])

    with rasterio.open('{}/{}_BAND6.tif'.format(cbers_address, sceneid)) as src:
        wgs_bounds = transform_bounds(
            *[src.crs, 'epsg:4326'] + list(src.bounds), densify_pts=21)

    if not utils.tile_exists(wgs_bounds, tile_z, tile_x, tile_y):
        raise TileOutsideBounds('Tile {}/{}/{} is outside image bounds'.format(
            tile_z, tile_x, tile_y))

    mercator_tile = mercantile.Tile(x=tile_x, y=tile_y, z=tile_z)
    tile_bounds = mercantile.xy_bounds(mercator_tile)

    addresses = ['{}/{}_BAND{}.tif'.format(cbers_address, sceneid, band) for band in rgb]

    _tiler = partial(utils.tile_band_worker, bounds=tile_bounds, tilesize=tilesize, nodata=0)
    with futures.ThreadPoolExecutor(max_workers=3) as executor:
        data, masks = zip(*list(executor.map(_tiler, addresses)))
        mask = np.all(masks, axis=0).astype(np.uint8) * 255

    return np.concatenate(data), mask
Пример #27
0
def read_tile(src_path, tile):
    """Benchmark rio-tiler.utils._tile_read."""
    tile_bounds = mercantile.xy_bounds(tile)
    # We make sure to not store things in cache.
    with rasterio.Env(GDAL_CACHEMAX=0, NUM_THREADS="all"):
        with rasterio.open(src_path) as src_dst:
            return reader.part(
                src_dst,
                tile_bounds,
                256,
                256,
                resampling_method="nearest",
                dst_crs=constants.WEB_MERCATOR_CRS,
            )
Пример #28
0
    def read_tile(self, z, x, y):
        """Read raster tile data and mask."""
        mercator_tile = mercantile.Tile(x=x, y=y, z=z)
        tile_bounds = mercantile.xy_bounds(mercator_tile)

        data, mask = tile_read(
            self.path,
            tile_bounds,
            self.tiles_size,
            indexes=self.indexes,
            nodata=self.nodata,
        )
        data = (data[0] + data[1]) / 2
        return data.astype(numpy.uint8), mask
Пример #29
0
def test_tile_read_wrong_nodata():
    """Return empty mask on wrong nodata."""
    # non-boundless tile covering the nodata part
    mercator_tile = mercantile.Tile(x=438217, y=801835, z=21)
    bounds = mercantile.xy_bounds(mercator_tile)
    arr, mask = utils.tile_read(S3_NODATA_PATH,
                                bounds,
                                256,
                                indexes=(1, 2, 3),
                                nodata=1000)
    assert arr.shape == (3, 256, 256)
    assert mask.all()

    # Mask boundless values
    mercator_tile = mercantile.Tile(x=109554, y=200458, z=19)
    bounds = mercantile.xy_bounds(mercator_tile)
    arr, mask = utils.tile_read(S3_NODATA_PATH,
                                bounds,
                                256,
                                indexes=(1, 2, 3),
                                nodata=1000)
    assert arr.shape == (3, 256, 256)
    assert not mask.all()
Пример #30
0
            def worker(tile):
                tick = time.monotonic()
                progress.update()

                x, y, z = map(str, [tile.x, tile.y, tile.z])

                try:
                    os.makedirs(os.path.join(args.out, z, x), exist_ok=True)
                except:
                    return tile, None, False

                path = os.path.join(args.out, z, x,
                                    "{}.{}".format(y, args.format))
                if os.path.isfile(path):  # already downloaded
                    return tile, None, True

                if args.type == "XYZ":
                    url = args.url.format(x=tile.x, y=tile.y, z=tile.z)
                elif args.type == "TMS":
                    tile.y = (2**tile.z) - tile.y - 1
                    url = args.url.format(x=tile.x, y=tile.y, z=tile.z)
                elif args.type == "WMS":
                    xmin, ymin, xmax, ymax = xy_bounds(tile)
                    url = args.url.format(xmin=xmin,
                                          ymin=ymin,
                                          xmax=xmax,
                                          ymax=ymax)

                res = tile_image_from_url(session, url, args.timeout)
                if res is None:  # let's retry once
                    res = tile_image_from_url(session, url, args.timeout)
                    if res is None:
                        return tile, url, False

                try:
                    tile_image_to_file(args.out, tile, res)
                    # cv2.imwrite(path, cv2.imdecode(np.fromstring(res.read(), np.uint8), cv2.IMREAD_COLOR))
                except OSError:
                    return tile, url, False

                tock = time.monotonic()

                time_for_req = tock - tick
                time_per_worker = args.workers / args.rate

                if time_for_req < time_per_worker:
                    time.sleep(time_per_worker - time_for_req)

                return tile, url, True
Пример #31
0
def optimize_group(group, quadkey):
    """Try to find the minimal number of assets to cover tile
    This optimization implies _both_ that
    - assets will be ordered in the MosaicJSON in order of sort of the entire tile
    - the total number of assets is kept to a minimum
    Computing the absolute minimum of assets to cover the tile may not in
    general be possible in finite time, so this is a naive method that should
    work relatively well for this use case.

    Returns group also sorted with respect to intersection of entire tile.
    """
    tile = mercantile.quadkey_to_tile(quadkey)
    tile_geom = box(*mercantile.xy_bounds(tile))
    final_assets = []

    while True:
        # Find intersection percent
        group['int_pct'] = group.geometry.intersection(
            tile_geom).area / tile_geom.area

        # Remove features with no tile overlap
        group = group.loc[group['int_pct'] > 0]

        if len(group) == 0:
            # There are many ocean/border tiles on the edges of available maps
            # that by definition don't have full coverage
            break

        # Sort by cover of region of tile that is left
        group = group.sort_values('int_pct', ascending=False)

        # Remove top asset and add to final_assets
        top_asset = group.iloc[0]
        group = group.iloc[1:]
        final_assets.append(top_asset)

        # Recompute tile_geom, removing overlap with top_asset
        tile_geom = tile_geom.difference(top_asset.geometry)

        # When total area is covered, stop
        if tile_geom.area - 1e-4 < 0:
            break

        if len(group) == 0:
            # There are many ocean/border tiles on the edges of available maps
            # that by definition don't have full coverage
            break

    return gpd.GeoDataFrame(final_assets)
def burn(tile, features, size):
    '''Burn tile with features.

    Args:
      tile: the mercantile tile to burn.
      features: the geojson features to burn.
      size: the size of burned image.

    Returns:
      image: rasterized file of size with features burned.
    '''

    # the value you want in the output raster where a shape exists
    burnval = 1
    shapes = ((geometry, burnval) for feature in features for geometry in feature_to_mercator(feature))

    bounds = mercantile.xy_bounds(tile)
    transform = from_bounds(*bounds, size, size)

    result = rasterize(shapes, out_shape=(size, size), transform=transform)
    return Image.fromarray(result, mode='P')