Ejemplo n.º 1
0
def test_fetch_stac_client_options(httpx, s3_get):
    # HTTP
    class MockResponse:
        def __init__(self, data):
            self.data = data

        def json(self):
            return json.loads(self.data)

    with open(STAC_PATH, "r") as f:
        httpx.get.return_value = MockResponse(f.read())

    with STACReader(
            "http://somewhereovertherainbow.io/mystac.json",
            fetch_options={
                "auth": ("user", "pass"),
                "headers": {
                    "Authorization": "Bearer token"
                },
            },
    ) as stac:
        assert stac.assets == ["red", "green", "blue"]
    httpx.get.assert_called_once()
    assert httpx.get.call_args[1]["auth"] == ("user", "pass")
    assert httpx.get.call_args[1]["headers"] == {
        "Authorization": "Bearer token"
    }
    s3_get.assert_not_called()

    with STACReader(
            "http://somewhereovertherainbow.io/mystac.json",
            fetch_options={
                "auth": ("user", "pass"),
                "headers": {
                    "Authorization": "Bearer token"
                },
            },
    ) as stac:
        assert stac.assets == ["red", "green", "blue"]

    # Check if it was cached
    assert httpx.get.call_count == 1
    s3_get.assert_not_called()

    # S3
    with open(STAC_PATH, "r") as f:
        s3_get.return_value = f.read()

    with STACReader(
            "s3://somewhereovertherainbow.io/mystac.json",
            fetch_options={"request_pays": True},
    ) as stac:
        assert stac.assets == ["red", "green", "blue"]
    httpx.assert_not_called()
    s3_get.assert_called_once()
    assert s3_get.call_args[1]["request_pays"]
    assert s3_get.call_args[0] == ("somewhereovertherainbow.io", "mystac.json")
Ejemplo n.º 2
0
def test_part_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    bbox = (-80.477, 33.4453, -79.737, 32.7988)

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.part(bbox, assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.part(bbox)

        data, mask = stac.part(bbox, assets="green")
        assert data.shape == (1, 73, 84)
        assert mask.shape == (73, 84)

        data, mask = stac.part(bbox, assets=("green",))
        assert data.shape == (1, 73, 84)
        assert mask.shape == (73, 84)

        data, mask = stac.part(bbox, expression="green/red")
        assert data.shape == (1, 73, 84)
        assert mask.shape == (73, 84)

        data, mask = stac.part(bbox, assets="green", max_size=30)
        assert data.shape == (1, 27, 30)
        assert mask.shape == (27, 30)

        with pytest.warns(ExpressionMixingWarning):
            data, _ = stac.part(bbox, assets=("green", "red"), expression="green/red")
            assert data.shape == (1, 73, 84)
Ejemplo n.º 3
0
def test_preview_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.preview(assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.preview()

        img = stac.preview(assets="green")
        assert img.data.shape == (1, 259, 255)
        assert img.mask.shape == (259, 255)
        assert img.band_names == ["green_1"]

        data, mask = stac.preview(assets=("green", ))
        assert data.shape == (1, 259, 255)
        assert mask.shape == (259, 255)

        img = stac.preview(expression="green/red")
        assert img.data.shape == (1, 259, 255)
        assert img.mask.shape == (259, 255)
        assert img.band_names == ["green/red"]

        with pytest.warns(ExpressionMixingWarning):
            img = stac.preview(assets=("green", "red"), expression="green/red")
            assert img.data.shape == (1, 259, 255)
            assert img.band_names == ["green/red"]

        img = stac.preview(
            assets=("green", "red"),
            asset_indexes={
                "green": (
                    1,
                    1,
                ),
                "red": 1,
            },
        )
        assert img.data.shape == (3, 259, 255)
        assert img.mask.shape == (259, 255)
        assert img.band_names == ["green_1", "green_1", "red_1"]

        img = stac.preview(assets=("green", "red"), indexes=1)
        assert img.data.shape == (2, 259, 255)
        assert img.mask.shape == (259, 255)
        assert img.band_names == ["green_1", "red_1"]

        img = stac.preview(
            assets=("green", "red"),
            asset_expression={
                "green": "b1*2,b1",
                "red": "b1*2"
            },
        )
        assert img.data.shape == (3, 259, 255)
        assert img.mask.shape == (259, 255)
        assert img.band_names == ["green_b1*2", "green_b1", "red_b1*2"]
Ejemplo n.º 4
0
def test_point_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.point(-80.477, 33.4453, assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.point(-80.477, 33.4453)

        data = stac.point(-80.477, 33.4453, assets="green")
        assert len(data) == 1

        data = stac.point(-80.477, 33.4453, assets=("green",))
        assert len(data) == 1

        data = stac.point(-80.477, 33.4453, expression="green/red")
        assert len(data) == 1

        with pytest.warns(ExpressionMixingWarning):
            data = stac.point(
                -80.477, 33.4453, assets=("green", "red"), expression="green/red"
            )
            assert len(data) == 1
Ejemplo n.º 5
0
def test_preview_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.preview(assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.preview()

        data, mask = stac.preview(assets="green")
        assert data.shape == (1, 259, 255)
        assert mask.shape == (259, 255)

        data, mask = stac.preview(assets=("green",))
        assert data.shape == (1, 259, 255)
        assert mask.shape == (259, 255)

        data, mask = stac.preview(expression="green/red")
        assert data.shape == (1, 259, 255)
        assert mask.shape == (259, 255)

        with pytest.warns(ExpressionMixingWarning):
            data, _ = stac.preview(assets=("green", "red"), expression="green/red")
            assert data.shape == (1, 259, 255)
Ejemplo n.º 6
0
def test_tile_valid(rio):
    """Should raise or return tiles."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(TileOutsideBounds):
            stac.tile(701, 102, 8, assets="green")

        with pytest.raises(InvalidAssetName):
            stac.tile(71, 102, 8, assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.tile(71, 102, 8)

        data, mask = stac.tile(71, 102, 8, assets="green")
        assert data.shape == (1, 256, 256)
        assert mask.shape == (256, 256)

        data, mask = stac.tile(71, 102, 8, assets=("green", ))
        assert data.shape == (1, 256, 256)
        assert mask.shape == (256, 256)

        data, mask = stac.tile(71, 102, 8, expression="green/red")
        assert data.shape == (1, 256, 256)
        assert mask.shape == (256, 256)

        data, mask = stac.tile(71,
                               102,
                               8,
                               assets=("green", "red"),
                               asset_expression="b1*2,b1")
        assert data.shape == (4, 256, 256)
        assert mask.shape == (256, 256)
Ejemplo n.º 7
0
def test_parse_expression():
    """."""
    with STACReader(STAC_PATH) as stac:
        assert sorted(stac.parse_expression("green*red+red/blue+2.0")) == [
            "blue",
            "green",
            "red",
        ]
Ejemplo n.º 8
0
def test_relative_assets():
    """Should return absolute href for assets"""
    with STACReader(STAC_REL_PATH) as stac:
        for (key, asset) in stac.item.assets.items():
            assert asset.get_absolute_href().startswith(PREFIX)
        assert len(stac.assets) == 5

        for asset in stac.assets:
            assert stac._get_asset_url(asset).startswith(PREFIX)
Ejemplo n.º 9
0
def test_feature_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    feat = {
        "type": "Feature",
        "properties": {},
        "geometry": {
            "type":
            "Polygon",
            "coordinates": [[
                [-80.013427734375, 33.03169299978312],
                [-80.3045654296875, 32.588477769459146],
                [-80.05462646484375, 32.42865847084369],
                [-79.45037841796875, 32.6093028087336],
                [-79.47235107421875, 33.43602551072033],
                [-79.89532470703125, 33.47956309444182],
                [-80.1068115234375, 33.37870592138779],
                [-80.30181884765625, 33.27084277265288],
                [-80.0628662109375, 33.146750228776455],
                [-80.013427734375, 33.03169299978312],
            ]],
        },
    }

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.feature(feat, assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.feature(feat)

        data, mask = stac.feature(feat, assets="green")
        assert data.shape == (1, 119, 97)
        assert mask.shape == (119, 97)

        data, mask = stac.feature(feat, assets=("green", ))
        assert data.shape == (1, 119, 97)
        assert mask.shape == (119, 97)

        data, mask = stac.feature(feat, expression="green/red")
        assert data.shape == (1, 119, 97)
        assert mask.shape == (119, 97)

        data, mask = stac.feature(feat, assets="green", max_size=30)
        assert data.shape == (1, 30, 25)
        assert mask.shape == (30, 25)

        with pytest.warns(ExpressionMixingWarning):
            data, _ = stac.feature(feat,
                                   assets=("green", "red"),
                                   expression="green/red")
            assert data.shape == (1, 119, 97)
Ejemplo n.º 10
0
def test_metadata_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.metadata(assets="vert")

        meta = stac.metadata(assets="green")
        assert meta["green"]

        meta = stac.metadata(assets=("green", "red"))
        assert meta["green"]
        assert meta["red"]
Ejemplo n.º 11
0
def test_stats_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.stats(assets="vert")

        stats = stac.stats(assets="green")
        assert stats["green"]

        stats = stac.stats(assets=("green", "red"), hist_options={"bins": 20})
        assert stats["green"]
        assert len(stats["green"][1]["histogram"][0]) == 20
        assert stats["red"]
Ejemplo n.º 12
0
def test_statistics_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.warns(UserWarning):
            stats = stac.statistics()
            assert stats["red"]
            assert stats["green"]
            assert stats["blue"]

        with pytest.raises(InvalidAssetName):
            stac.statistics(assets="vert")

        stats = stac.statistics(assets="green")
        assert stats["green"]
        assert isinstance(stats["green"]["1"], BandStatistics)

        stats = stac.statistics(assets=("green", "red"),
                                hist_options={"bins": 20})
        assert len(stats) == 2
        assert len(stats["green"]["1"]["histogram"][0]) == 20

        # Check that asset_expression is passed
        stats = stac.statistics(assets=("green", "red"),
                                asset_expression={
                                    "green": "b1*2",
                                    "red": "b1+100"
                                })
        assert stats["green"]
        assert isinstance(stats["green"]["b1*2"], BandStatistics)
        assert isinstance(stats["red"]["b1+100"], BandStatistics)

        # Check that asset_indexes is passed
        stats = stac.statistics(assets=("green", "red"),
                                asset_indexes={
                                    "green": 1,
                                    "red": 1
                                })
        assert stats["green"]
        assert isinstance(stats["green"]["1"], BandStatistics)
        assert isinstance(stats["red"]["1"], BandStatistics)

        # Check that asset_indexes is passed
        stats = stac.statistics(assets=("green", "red"), indexes=1)
        assert stats["green"]
        assert isinstance(stats["green"]["1"], BandStatistics)
        assert isinstance(stats["red"]["1"], BandStatistics)
Ejemplo n.º 13
0
def test_info_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.info(assets="vert")

        with pytest.warns(UserWarning):
            meta = stac.info()
            assert meta["red"]
            assert meta["green"]
            assert meta["blue"]

        meta = stac.info(assets="green")
        assert meta["green"]

        meta = stac.info(assets=("green", "red"))
        assert meta["green"]
        assert meta["red"]
Ejemplo n.º 14
0
def yield_estimation(geojson):

    scenes = fetch_stac_scenes(geojson)

    best_scene = least_cloud_cover_date(scenes, geojson)

    # Scene path from the AWS URL for element84 query. ex: S2B_14TQN_20200708_0_L2A
    scene_path = urlparse(best_scene).path.split("/")[-2]

    stac_item = "https://earth-search.aws.element84.com/v0/collections/sentinel-s2-l2a-cogs/items/{sceneid}"
    stac_asset = stac_item.format(sceneid=scene_path)

    bounds = featurebounds(geojson)

    with STACReader(stac_asset) as cog:
        ndvi, _ = cog.part(bounds, expression="(B08-B04)/(B08+B04)")
        # Crop and resample scene classification band
        scl_band, mask = cog.part(
            bounds,
            resampling_method="nearest",
            height=ndvi.shape[1],
            width=ndvi.shape[2],
            assets="SCL",
            max_size=None,
        )

    # Apply cloud mask
    masked = np.ma.where((scl_band < 4) | (scl_band > 6), 0, 1)

    # NDVI as a MaskedArray
    ndvi_masked = ImageData(ndvi, masked).as_masked()

    # print("\nMax NDVI: {m}".format(m=ndvi_masked.max()))
    # print("Mean NDVI: {m}".format(m=ndvi_masked.mean()))
    # print("Median NDVI: {m}".format(m=np.median(ndvi_masked.data)))
    # print("Min NDVI: {m}".format(m=ndvi_masked.min()))

    yield_estimate = 11.359 * math.exp(3.1 * ndvi_masked.mean())

    return yield_estimate
Ejemplo n.º 15
0
 def __init__(self, src_path: str, **kwargs):
     """Initialize STACTiles object."""
     self.path = src_path
     with STACReader(self.path, **kwargs) as stac:
         self.assets = stac.assets
         self.stac = stac
Ejemplo n.º 16
0
def test_fetch_stac(requests, s3_get):
    # Local path
    with STACReader(STAC_PATH) as stac:
        assert stac.minzoom == 0
        assert stac.maxzoom == 30
        assert stac.bounds
        assert stac.center
        assert stac.spatial_info
        assert stac.filepath == STAC_PATH
        assert stac.assets == ["red", "green", "blue"]
    requests.assert_not_called()
    s3_get.assert_not_called()

    # Load from dict
    with STACReader(None, item=stac_item) as stac:
        assert stac.minzoom == 0
        assert stac.maxzoom == 30
        assert not stac.filepath
        assert stac.assets == ["red", "green", "blue"]
    requests.assert_not_called()
    s3_get.assert_not_called()

    # Exclude red
    with STACReader(STAC_PATH, exclude_assets={"red"}) as stac:
        assert stac.assets == ["green", "blue"]
    requests.assert_not_called()
    s3_get.assert_not_called()

    # Only include red asset
    with STACReader(STAC_PATH, include_assets={"red"}) as stac:
        assert stac.assets == ["red"]
    requests.assert_not_called()
    s3_get.assert_not_called()

    # Only include png
    with STACReader(STAC_PATH, include_asset_types={"image/png"}) as stac:
        assert "thumbnail" in stac.assets
    requests.assert_not_called()
    s3_get.assert_not_called()

    # Include assets/types
    with STACReader(
        STAC_PATH,
        include_assets={"thumbnail", "overview"},
        include_asset_types={"image/png"},
    ) as stac:
        assert stac.assets == ["thumbnail"]
    requests.assert_not_called()
    s3_get.assert_not_called()

    # No valid assets
    with pytest.raises(MissingAssets):
        with STACReader(STAC_PATH, include_assets={"B1"}) as stac:
            pass
    requests.assert_not_called()
    s3_get.assert_not_called()

    # HTTP
    class MockResponse:
        def __init__(self, data):
            self.data = data

        def json(self):
            return json.loads(self.data)

    with open(STAC_PATH, "r") as f:
        requests.get.return_value = MockResponse(f.read())

    with STACReader("http://somewhereovertherainbow.io/mystac.json") as stac:
        assert stac.assets == ["red", "green", "blue"]
    requests.get.assert_called_once()
    s3_get.assert_not_called()
    requests.mock_reset()

    # S3
    with open(STAC_PATH, "r") as f:
        s3_get.return_value = f.read()

    with STACReader("s3://somewhereovertherainbow.io/mystac.json") as stac:
        assert stac.assets == ["red", "green", "blue"]
    requests.assert_not_called()
    s3_get.assert_called_once()
    assert s3_get.call_args[0] == ("somewhereovertherainbow.io", "mystac.json")
Ejemplo n.º 17
0
def test_tile_valid(rio):
    """Should raise or return tiles."""
    rio.open = mock_rasterio_open

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(TileOutsideBounds):
            stac.tile(701, 102, 8, assets="green")

        with pytest.raises(InvalidAssetName):
            stac.tile(71, 102, 8, assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.tile(71, 102, 8)

        img = stac.tile(71, 102, 8, assets="green")
        assert img.data.shape == (1, 256, 256)
        assert img.mask.shape == (256, 256)
        assert img.band_names == ["green_1"]

        data, mask = stac.tile(71, 102, 8, assets=("green", ))
        assert data.shape == (1, 256, 256)
        assert mask.shape == (256, 256)

        img = stac.tile(71, 102, 8, expression="green/red")
        assert img.data.shape == (1, 256, 256)
        assert img.mask.shape == (256, 256)
        # Note: Here we loose the information about the band
        assert img.band_names == ["green/red"]

        with pytest.warns(ExpressionMixingWarning):
            img = stac.tile(71,
                            102,
                            8,
                            assets=("green", "red"),
                            expression="green/red")
            assert img.data.shape == (1, 256, 256)
            assert img.band_names == ["green/red"]

        img = stac.tile(
            71,
            102,
            8,
            assets=("green", "red"),
            asset_indexes={
                "green": (
                    1,
                    1,
                ),
                "red": 1,
            },
        )
        assert img.data.shape == (3, 256, 256)
        assert img.mask.shape == (256, 256)
        assert img.band_names == ["green_1", "green_1", "red_1"]

        # check backward compatibility for `indexes`
        img = stac.tile(
            71,
            102,
            8,
            assets=("green", "red"),
            indexes=1,
        )
        assert img.data.shape == (2, 256, 256)
        assert img.mask.shape == (256, 256)
        assert img.band_names == ["green_1", "red_1"]

        img = stac.tile(
            71,
            102,
            8,
            assets=("green", "red"),
            asset_expression={
                "green": "b1*2,b1",
                "red": "b1*2"
            },
        )
        assert img.data.shape == (3, 256, 256)
        assert img.mask.shape == (256, 256)
        assert img.band_names == ["green_b1*2", "green_b1", "red_b1*2"]
Ejemplo n.º 18
0
 def _reader(src_path: str, *args, **kwargs) -> ImageData:
     """Read tile from an asset"""
     with STACReader(src_path) as stac:
         return stac.tile(*args, **kwargs)
Ejemplo n.º 19
0
def test_part_valid(rio):
    """Should raise or return data."""
    rio.open = mock_rasterio_open

    bbox = (-80.477, 32.7988, -79.737, 33.4453)

    with STACReader(STAC_PATH) as stac:
        with pytest.raises(InvalidAssetName):
            stac.part(bbox, assets="vert")

        # missing asset/expression
        with pytest.raises(MissingAssets):
            stac.part(bbox)

        img = stac.part(bbox, assets="green")
        assert img.data.shape == (1, 73, 83)
        assert img.mask.shape == (73, 83)
        assert img.band_names == ["green_1"]

        data, mask = stac.part(bbox, assets=("green", ))
        assert data.shape == (1, 73, 83)
        assert mask.shape == (73, 83)

        img = stac.part(bbox, expression="green/red")
        assert img.data.shape == (1, 73, 83)
        assert img.mask.shape == (73, 83)
        assert img.band_names == ["green/red"]

        data, mask = stac.part(bbox, assets="green", max_size=30)
        assert data.shape == (1, 27, 30)
        assert mask.shape == (27, 30)

        with pytest.warns(ExpressionMixingWarning):
            img = stac.part(bbox,
                            assets=("green", "red"),
                            expression="green/red")
            assert img.data.shape == (1, 73, 83)
            assert img.band_names == ["green/red"]

        img = stac.part(
            bbox,
            assets=("green", "red"),
            asset_indexes={
                "green": (
                    1,
                    1,
                ),
                "red": 1,
            },
        )
        assert img.data.shape == (3, 73, 83)
        assert img.mask.shape == (73, 83)
        assert img.band_names == ["green_1", "green_1", "red_1"]

        img = stac.part(bbox, assets=("green", "red"), indexes=1)
        assert img.data.shape == (2, 73, 83)
        assert img.mask.shape == (73, 83)
        assert img.band_names == ["green_1", "red_1"]

        img = stac.part(
            bbox,
            assets=("green", "red"),
            asset_expression={
                "green": "b1*2,b1",
                "red": "b1*2"
            },
        )
        assert img.data.shape == (3, 73, 83)
        assert img.mask.shape == (73, 83)
        assert img.band_names == ["green_b1*2", "green_b1", "red_b1*2"]