Ejemplo n.º 1
0
def main(event, context):
    """Handler."""
    logger.info(event)

    sceneid = event["sceneid"]
    band = event["band"]

    scene_params = _sentinel_parse_scene_id(sceneid)
    band_key = f"{scene_params['key']}/B{band}.jp2"

    logger.info(f"Downloading {band_key}")
    src_path = f"/tmp/{band}.jp2"
    with open(src_path, "wb") as f:
        s3.download_fileobj("sentinel-s2-l1c",
                            band_key,
                            f,
                            ExtraArgs={"RequestPayer": "requester"})

    logger.info(f"Translating {band_key} to COG")
    config = dict(NUM_THREADS=100, GDAL_TIFF_OVR_BLOCKSIZE=128)

    output_profile = {
        "driver": "GTiff",
        "interleave": "pixel",
        "tiled": True,
        "blockxsize": 256,
        "blockysize": 256,
        "compress": "DEFLATE",
    }

    cog_path = f"/tmp/{band}.tif"
    cog_translate(
        src_path,
        cog_path,
        output_profile,
        nodata=0,
        in_memory=False,
        config=config,
        quiet=True,
    )

    params = {
        "ACL": "public-read",
        "Metadata": {
            "scene": sceneid,
            "bands": band
        },
        "ContentType": "image/tiff",
    }

    key = band_key.replace(".jp2", ".tif")
    if PREFIX:
        key = f"{PREFIX}/{key}"

    logger.info(f"Uploading {key}")
    with open(cog_path, "rb") as data:
        s3.upload_fileobj(data, BUCKET, key, ExtraArgs=params)
Ejemplo n.º 2
0
def test_sentinel_id_valid_strip():
    """Parse sentinel-2 valid sceneid with leading 0 and return metadata."""
    scene = "S2A_tile_20170323_07SNC_0"
    expected_content = {
        "acquisitionDay": "23",
        "acquisitionMonth": "03",
        "acquisitionYear": "2017",
        "key": "tiles/7/S/NC/2017/3/23/0",
        "lat": "S",
        "num": "0",
        "satellite": "A",
        "scene": "S2A_tile_20170323_07SNC_0",
        "sensor": "2",
        "sq": "NC",
        "utm": "07",
    }

    assert sentinel2._sentinel_parse_scene_id(scene) == expected_content
Ejemplo n.º 3
0
def tilejson_handler(
    event: Dict,
    scene: str,
    tile_format: str = "png",
    tile_scale: int = 1,
    **kwargs: Any,
) -> Tuple[str, str, str]:
    """Handle /tilejson.json requests."""
    # HACK
    token = event["multiValueQueryStringParameters"].get("access_token")
    if token:
        kwargs.update(dict(access_token=token[0]))

    qs = urllib.parse.urlencode(list(kwargs.items()))
    tile_url = f"{APP.host}/s2/tiles/{scene}/{{z}}/{{x}}/{{y}}@{tile_scale}x.{tile_format}?{qs}"

    scene_params = sentinel2._sentinel_parse_scene_id(scene)
    sentinel_address = "s3://{}/{}/B{}.jp2".format(sentinel2.SENTINEL_BUCKET,
                                                   scene_params["key"], "04")
    with rasterio.open(sentinel_address) as src_dst:
        bounds = warp.transform_bounds(*[src_dst.crs, "epsg:4326"] +
                                       list(src_dst.bounds),
                                       densify_pts=21)
        minzoom, maxzoom = get_zooms(src_dst)
        center = [(bounds[0] + bounds[2]) / 2, (bounds[1] + bounds[3]) / 2,
                  minzoom]

    meta = dict(
        bounds=bounds,
        center=center,
        minzoom=minzoom,
        maxzoom=maxzoom,
        name=scene,
        tilejson="2.1.0",
        tiles=[tile_url],
    )
    return ("OK", "application/json", json.dumps(meta))
Ejemplo n.º 4
0
def test_sentinel_id_invalid():
    """Raises error on invalid sentinel-2 sceneid."""
    scene = "S2A_tile_20170323_17SNC"
    with pytest.raises(InvalidSentinelSceneId):
        sentinel2._sentinel_parse_scene_id(scene)
Ejemplo n.º 5
0
def sentinel2_tile(sceneid,
                   tile_x,
                   tile_y,
                   tile_z,
                   bands=("04", "03", "02"),
                   tilesize=256,
                   percents='',
                   **kwargs):
    """
    Create mercator tile from Sentinel-2 data.

    Attributes
    ----------
    sceneid : str
        Sentinel-2 sceneid.
    tile_x : int
        Mercator tile X index.
    tile_y : int
        Mercator tile Y index.
    tile_z : int
        Mercator tile ZOOM level.
    bands : tuple, str, optional (default: ('04', '03', '02'))
        Bands index for the RGB combination.
    tilesize : int, optional (default: 256)
        Output image size.
    kwargs: dict, optional
        These will be passed to the 'rio_tiler.utils._tile_read' function.

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

    """
    if not isinstance(bands, tuple):
        bands = tuple((bands, ))

    for band in bands:
        if band not in SENTINEL_BANDS:
            raise InvalidBandName(
                "{} is not a valid Sentinel band name".format(band))

    scene_params = sentinel2._sentinel_parse_scene_id(sceneid)
    sentinel_address = "{}/{}".format(SENTINEL_BUCKET, scene_params["key"])

    addresses = ["{}/B{}.jp2".format(sentinel_address, band) for band in bands]

    values = []
    percents = percents.split(',')
    i = 0
    for address in addresses:
        with rasterio.open(address) as src:
            bounds = warp.transform_bounds(src.crs,
                                           "epsg:4326",
                                           *src.bounds,
                                           densify_pts=21)
            if int(percents[i]) != 0 and int(percents[i + 1]) != 100:
                overviews = src.overviews(1)
                if len(overviews) > 0:
                    d = src.read(
                        out_shape=(1,
                                   int(src.height /
                                       overviews[len(overviews) - 1]),
                                   int(src.width /
                                       overviews[len(overviews) - 1])))
                else:
                    d = src.read()

                dflatten_full = numpy.array(d.flatten())
                dflatten = dflatten_full[dflatten_full > 0]

                p_start, p_end = numpy.percentile(dflatten,
                                                  (int(percents[i]),
                                                   (int(percents[i + 1]))))
                values.append([p_start, p_end])
            else:
                values.append([None, None])
            i += 2

    if not utils.tile_exists(bounds, tile_z, tile_x, tile_y):
        # raise TileOutsideBounds(
        #     "Tile {}/{}/{} is outside image bounds".format(tile_z, tile_x, tile_y)
        # )
        return None, None

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

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

    new_data = list(data)
    has_modification = False
    for ds in range(0, len(new_data)):
        if values[ds][0] is not None and values[ds][1] is not None:
            has_modification = True
            new_data[ds] = rescale_intensity(new_data[ds],
                                             in_range=(values[ds][0],
                                                       values[ds][1]),
                                             out_range=(0, 255))

    if has_modification == True:
        data = numpy.array(new_data).astype(numpy.uint8)

    return numpy.concatenate(data), mask
Ejemplo n.º 6
0
def test_sentinel_newidl2a_valid():
    """Parse sentinel-2 valid sceneid and return metadata."""
    expected_content = {
        "acquisitionDay":
        "29",
        "acquisitionMonth":
        "07",
        "acquisitionYear":
        "2017",
        "aws_bucket":
        "s3://sentinel-s2-l2a",
        "aws_prefix":
        "tiles/19/U/DP/2017/7/29/0",
        "key":
        "tiles/19/U/DP/2017/7/29/0",
        "lat":
        "U",
        "num":
        "0",
        "satellite":
        "A",
        "scene":
        "S2A_L2A_20170729_19UDP_0",
        "sensor":
        "2",
        "sq":
        "DP",
        "utm":
        "19",
        "processingLevel":
        "L2A",
        "preview_file":
        "R60m/TCI.jp2",
        "preview_prefix":
        "R60m",
        "bands": [
            "01",
            "02",
            "03",
            "04",
            "05",
            "06",
            "07",
            "08",
            "09",
            "11",
            "12",
            "8A",
        ],
        "valid_bands": [
            "01",
            "02",
            "03",
            "04",
            "05",
            "06",
            "07",
            "08",
            "09",
            "11",
            "12",
            "8A",
            "AOT",
            "SCL",
            "WVP",
        ],
    }
    assert sentinel2._sentinel_parse_scene_id(
        SENTINEL_SCENE_L2) == expected_content
Ejemplo n.º 7
0
def test_sentinel_id_valid_strip():
    """Parse sentinel-2 valid sceneid with leading 0 and return metadata."""
    expected_content = {
        "acquisitionDay":
        "23",
        "acquisitionMonth":
        "03",
        "acquisitionYear":
        "2017",
        "aws_bucket":
        "s3://sentinel-s2-l1c",
        "aws_prefix":
        "tiles/7/S/NC/2017/3/23/0",
        "key":
        "tiles/7/S/NC/2017/3/23/0",
        "lat":
        "S",
        "num":
        "0",
        "satellite":
        "A",
        "scene":
        "S2A_tile_20170323_07SNC_0",
        "sensor":
        "2",
        "sq":
        "NC",
        "utm":
        "07",
        "processingLevel":
        "L1C",
        "preview_file":
        "preview.jp2",
        "preview_prefix":
        "preview",
        "bands": [
            "02",
            "03",
            "04",
            "08",
            "05",
            "06",
            "07",
            "11",
            "12",
            "8A",
            "01",
            "09",
            "10",
        ],
        "valid_bands": [
            "02",
            "03",
            "04",
            "08",
            "05",
            "06",
            "07",
            "11",
            "12",
            "8A",
            "01",
            "09",
            "10",
        ],
    }

    with pytest.warns(DeprecationWarning):
        assert (sentinel2._sentinel_parse_scene_id("S2A_tile_20170323_07SNC_0")
                == expected_content)