Пример #1
0
    def test_bands(self) -> None:
        item = pystac.Item.from_file(self.BANDS_IN_ITEM_URI)

        # Get
        self.assertIn("eo:bands", item.properties)
        bands = EOExtension.ext(item).bands
        assert bands is not None
        self.assertEqual(
            list(map(lambda x: x.name, bands)), ["band1", "band2", "band3", "band4"]
        )

        # Set
        new_bands = [
            Band.create(name="red", description=Band.band_description("red")),
            Band.create(name="green", description=Band.band_description("green")),
            Band.create(name="blue", description=Band.band_description("blue")),
        ]

        EOExtension.ext(item).bands = new_bands
        self.assertEqual(
            "Common name: red, Range: 0.6 to 0.7",
            item.properties["eo:bands"][0]["description"],
        )
        self.assertEqual(len(EOExtension.ext(item).bands or []), 3)
        item.validate()
Пример #2
0
    def test_item_ext_add_to(self) -> None:
        item = pystac.Item.from_file(self.PLAIN_ITEM)
        self.assertNotIn(EOExtension.get_schema_uri(), item.stac_extensions)

        _ = EOExtension.ext(item, add_if_missing=True)

        self.assertIn(EOExtension.get_schema_uri(), item.stac_extensions)
Пример #3
0
    def test_asset_ext_add_to(self) -> None:
        item = pystac.Item.from_file(self.PLAIN_ITEM)
        self.assertNotIn(EOExtension.get_schema_uri(), item.stac_extensions)
        asset = item.assets["thumbnail"]

        _ = EOExtension.ext(asset, add_if_missing=True)

        self.assertIn(EOExtension.get_schema_uri(), item.stac_extensions)
Пример #4
0
    def test_summaries_adds_uri(self) -> None:
        col = pystac.Collection.from_file(self.EO_COLLECTION_URI)
        col.stac_extensions = []
        self.assertRaisesRegex(
            pystac.ExtensionNotImplemented,
            r"Could not find extension schema URI.*",
            EOExtension.summaries,
            col,
            False,
        )
        _ = EOExtension.summaries(col, add_if_missing=True)

        self.assertIn(EOExtension.get_schema_uri(), col.stac_extensions)

        EOExtension.remove_from(col)
        self.assertNotIn(EOExtension.get_schema_uri(), col.stac_extensions)
Пример #5
0
def add_assets(item, granule, endpoint, version):
    item_id = granule.GranuleUR.cdata
    product = item_id.split(".")[1]
    if product == "S30":
        band_info = sentinel_band_info
        url = f"https://{endpoint}/lp-prod-protected/HLSS30.{version}/{item_id}/"
        public_url = f"https://{endpoint}/lp-prod-public/HLSS30.{version}/{item_id}/"

    if product == "L30":
        band_info = landsat_band_info
        url = f"https://{endpoint}/lp-prod-protected/HLSL30.{version}/{item_id}/"
        public_url = f"https://{endpoint}/lp-prod-public/HLSL30.{version}/{item_id}/"

    url_template = url + "{}.{}.tif"

    for band_id, band_info in band_info.items():
        band_url = url_template.format(item_id, band_id)
        asset = pystac.Asset(href=band_url,
                             media_type=pystac.MediaType.COG,
                             roles=["data"])
        bands = [band_info["band"]]
        EOExtension.ext(asset).bands = bands
        item.add_asset(band_id, asset)

    thumbnail_url = f"{public_url}{item_id}.jpg"
    thumbnail_asset = pystac.Asset(href=thumbnail_url,
                                   media_type=pystac.MediaType.JPEG,
                                   roles=["thumbnail"])
    item.add_asset("thumbnail", thumbnail_asset)
    item.set_self_href(f"{public_url}{item_id}_stac.json")
Пример #6
0
    def test_extension_not_implemented(self) -> None:
        # Should raise exception if Item does not include extension URI
        item = pystac.Item.from_file(self.PLAIN_ITEM)

        with self.assertRaises(pystac.ExtensionNotImplemented):
            _ = EOExtension.ext(item)

        # Should raise exception if owning Item does not include extension URI
        asset = item.assets["thumbnail"]

        with self.assertRaises(pystac.ExtensionNotImplemented):
            _ = EOExtension.ext(asset)

        # Should succeed if Asset has no owner
        ownerless_asset = pystac.Asset.from_dict(asset.to_dict())
        _ = EOExtension.ext(ownerless_asset)
Пример #7
0
    def test_asset_ext_add_to_ownerless_asset(self) -> None:
        item = pystac.Item.from_file(self.PLAIN_ITEM)
        asset_dict = item.assets["thumbnail"].to_dict()
        asset = pystac.Asset.from_dict(asset_dict)

        with self.assertRaises(pystac.STACError):
            _ = EOExtension.ext(asset, add_if_missing=True)
Пример #8
0
    def test_cloud_cover(self) -> None:
        item = pystac.Item.from_file(self.LANDSAT_EXAMPLE_URI)

        # Get
        self.assertIn("eo:cloud_cover", item.properties)
        cloud_cover = EOExtension.ext(item).cloud_cover
        self.assertEqual(cloud_cover, 78)

        # Set
        EOExtension.ext(item).cloud_cover = 50
        self.assertEqual(item.properties["eo:cloud_cover"], 50)

        # Get from Asset
        b2_asset = item.assets["B2"]
        self.assertEqual(
            EOExtension.ext(b2_asset).cloud_cover, EOExtension.ext(item).cloud_cover
        )

        b3_asset = item.assets["B3"]
        self.assertEqual(EOExtension.ext(b3_asset).cloud_cover, 20)

        # Set on Asset
        EOExtension.ext(b2_asset).cloud_cover = 10
        self.assertEqual(EOExtension.ext(b2_asset).cloud_cover, 10)

        item.validate()
Пример #9
0
    def test_asset_bands(self) -> None:
        item = pystac.Item.from_file(self.LANDSAT_EXAMPLE_URI)

        # Get

        b1_asset = item.assets["B1"]
        asset_bands = EOExtension.ext(b1_asset).bands
        assert asset_bands is not None
        self.assertEqual(len(asset_bands), 1)
        self.assertEqual(asset_bands[0].name, "B1")
        self.assertEqual(asset_bands[0].solar_illumination, 2000)

        index_asset = item.assets["index"]
        asset_bands = EOExtension.ext(index_asset).bands
        self.assertIs(None, asset_bands)

        # No asset specified
        item_bands = EOExtension.ext(item).bands
        self.assertIsNot(None, item_bands)

        # Set
        b2_asset = item.assets["B2"]
        self.assertEqual(get_opt(EOExtension.ext(b2_asset).bands)[0].name, "B2")
        EOExtension.ext(b2_asset).bands = EOExtension.ext(b1_asset).bands

        new_b2_asset_bands = EOExtension.ext(item.assets["B2"]).bands

        self.assertEqual(get_opt(new_b2_asset_bands)[0].name, "B1")

        item.validate()

        # Check adding a new asset
        new_bands = [
            Band.create(
                name="red",
                description=Band.band_description("red"),
                solar_illumination=1900,
            ),
            Band.create(
                name="green",
                description=Band.band_description("green"),
                solar_illumination=1950,
            ),
            Band.create(
                name="blue",
                description=Band.band_description("blue"),
                solar_illumination=2000,
            ),
        ]
        asset = pystac.Asset(href="some/path.tif", media_type=pystac.MediaType.GEOTIFF)
        EOExtension.ext(asset).bands = new_bands
        item.add_asset("test", asset)

        self.assertEqual(len(item.assets["test"].extra_fields["eo:bands"]), 3)
Пример #10
0
    def test_reads_asset_bands_in_pre_1_0_version(self) -> None:
        item = pystac.Item.from_file(
            TestCases.get_path(
                "data-files/examples/0.9.0/item-spec/examples/" "landsat8-sample.json"
            )
        )

        bands = EOExtension.ext(item.assets["B9"]).bands

        self.assertEqual(len(bands or []), 1)
        self.assertEqual(get_opt(bands)[0].common_name, "cirrus")
Пример #11
0
    def test_add_to(self) -> None:
        item = Item.from_file(self.PLAIN_ITEM)
        self.assertNotIn(EOExtension.get_schema_uri(), item.stac_extensions)

        # Check that the URI gets added to stac_extensions
        EOExtension.add_to(item)
        self.assertIn(EOExtension.get_schema_uri(), item.stac_extensions)

        # Check that the URI only gets added once, regardless of how many times add_to
        # is called.
        EOExtension.add_to(item)
        EOExtension.add_to(item)

        eo_uris = [
            uri for uri in item.stac_extensions if uri == EOExtension.get_schema_uri()
        ]
        self.assertEqual(len(eo_uris), 1)
Пример #12
0
    def test_item_apply(self) -> None:
        item = pystac.Item.from_file(self.LANDSAT_EXAMPLE_URI)
        eo_ext = EOExtension.ext(item)
        test_band = Band.create(name="test")

        self.assertEqual(eo_ext.cloud_cover, 78)
        self.assertNotIn(test_band, eo_ext.bands or [])

        eo_ext.apply(bands=[test_band], cloud_cover=15)
        assert eo_ext.bands is not None

        self.assertEqual(test_band.to_dict(), eo_ext.bands[0].to_dict())
        self.assertEqual(eo_ext.cloud_cover, 15)
Пример #13
0
    def test_summaries(self) -> None:
        col = pystac.Collection.from_file(self.EO_COLLECTION_URI)
        eo_summaries = EOExtension.summaries(col)

        # Get

        cloud_cover_summaries = eo_summaries.cloud_cover
        assert cloud_cover_summaries is not None
        self.assertEqual(cloud_cover_summaries.minimum, 0.0)
        self.assertEqual(cloud_cover_summaries.maximum, 80.0)

        bands = eo_summaries.bands
        assert bands is not None
        self.assertEqual(len(bands), 11)

        # Set

        eo_summaries.cloud_cover = RangeSummary(1.0, 2.0)
        eo_summaries.bands = [Band.create(name="test")]

        col_dict = col.to_dict()
        self.assertEqual(len(col_dict["summaries"]["eo:bands"]), 1)
        self.assertEqual(col_dict["summaries"]["eo:cloud_cover"]["minimum"], 1.0)
Пример #14
0
 def test_asset_bands_s2(self) -> None:
     item = pystac.Item.from_file(self.S2_ITEM_URI)
     mtd_asset = item.get_assets()["mtd"]
     self.assertIsNone(EOExtension.ext(mtd_asset).bands)
Пример #15
0
def process_eo(item, granule):
    eo_extension = EOExtension.ext(item, add_if_missing=True)
    for attribute in granule.AdditionalAttributes.AdditionalAttribute:
        if attribute.Name == "CLOUD_COVERAGE":
            eo_extension.cloud_cover = float(attribute.Values.Value.cdata)
Пример #16
0
    def test_read_eo_items_are_heritable(self) -> None:
        cat = TestCases.test_case_5()
        item = next(iter(cat.get_all_items()))

        self.assertTrue(EOExtension.has_extension(item))
Пример #17
0
def to_pystac_item(
    dataset: DatasetDoc,
    stac_item_destination_url: str,
    dataset_location: Optional[str] = None,
    odc_dataset_metadata_url: Optional[str] = None,
    explorer_base_url: Optional[str] = None,
    collection_url: Optional[str] = None,
) -> pystac.Item:
    """
    Convert the given ODC Dataset into a Stac Item document.

    Note: You may want to call `validate_item(doc)` on the outputs to find any
    incomplete properties.

    :param collection_url: URL to the Stac Collection. Either this or an explorer_base_url
                           should be specified for Stac compliance.
    :param stac_item_destination_url: Public 'self' URL where the stac document will be findable.
    :param dataset_location: Use this location instead of picking from dataset.locations
                             (for calculating relative band paths)
    :param odc_dataset_metadata_url: Public URL for the original ODC dataset yaml document
    :param explorer_base_url: An Explorer instance that contains this dataset.
                              Will allow links to things such as the product definition.
    """

    if dataset.geometry is not None:
        geom = Geometry(dataset.geometry, CRS(dataset.crs))
        wgs84_geometry = geom.to_crs(CRS("epsg:4326"), math.inf)

        geometry = wgs84_geometry.json
        bbox = wgs84_geometry.boundingbox
    else:
        geometry = None
        bbox = None

    properties = eo3_to_stac_properties(dataset, title=dataset.label)
    properties.update(_lineage_fields(dataset.lineage))

    dt = properties["datetime"]
    del properties["datetime"]

    # TODO: choose remote if there's multiple locations?
    # Without a dataset location, all paths will be relative.
    dataset_location = dataset_location or (dataset.locations[0]
                                            if dataset.locations else None)

    item = Item(
        id=str(dataset.id),
        datetime=dt,
        properties=properties,
        geometry=geometry,
        bbox=bbox,
        collection=dataset.product.name,
    )

    # Add links
    if stac_item_destination_url:
        item.links.append(
            Link(
                rel="self",
                media_type=MediaType.JSON,
                target=stac_item_destination_url,
            ))
    if odc_dataset_metadata_url:
        item.links.append(
            Link(
                title="ODC Dataset YAML",
                rel="odc_yaml",
                media_type="text/yaml",
                target=odc_dataset_metadata_url,
            ))

    for link in _odc_links(explorer_base_url, dataset, collection_url):
        item.links.append(link)

    EOExtension.ext(item, add_if_missing=True)

    if dataset.geometry:
        proj = ProjectionExtension.ext(item, add_if_missing=True)
        epsg, wkt = _get_projection(dataset)
        if epsg is not None:
            proj.apply(epsg=epsg, **_proj_fields(dataset.grids))
        elif wkt is not None:
            proj.apply(wkt2=wkt, **_proj_fields(dataset.grids))
        else:
            raise STACError(
                "Projection extension requires either epsg or wkt for crs.")

    # To pass validation, only add 'view' extension when we're using it somewhere.
    if any(k.startswith("view:") for k in properties.keys()):
        ViewExtension.ext(item, add_if_missing=True)

    # Add assets that are data
    for name, measurement in dataset.measurements.items():
        if not dataset_location and not measurement.path:
            # No URL to link to. URL is mandatory for Stac validation.
            continue

        asset = Asset(
            href=_uri_resolve(dataset_location, measurement.path),
            media_type=_media_type(Path(measurement.path)),
            title=name,
            roles=["data"],
        )
        eo = EOExtension.ext(asset)

        # TODO: pull out more information about the band
        band = Band.create(name)
        eo.apply(bands=[band])

        if dataset.grids:
            proj_fields = _proj_fields(dataset.grids, measurement.grid)
            if proj_fields is not None:
                proj = ProjectionExtension.ext(asset)
                # Not sure how this handles None for an EPSG code
                proj.apply(
                    shape=proj_fields["shape"],
                    transform=proj_fields["transform"],
                    epsg=epsg,
                )

        item.add_asset(name, asset=asset)

    # Add assets that are accessories
    for name, measurement in dataset.accessories.items():
        if not dataset_location and not measurement.path:
            # No URL to link to. URL is mandatory for Stac validation.
            continue

        asset = Asset(
            href=_uri_resolve(dataset_location, measurement.path),
            media_type=_media_type(Path(measurement.path)),
            title=_asset_title_fields(name),
            roles=_asset_roles_fields(name),
        )

        item.add_asset(name, asset=asset)

    return item
Пример #18
0
    def test_extend_invalid_object(self) -> None:
        link = pystac.Link("child", "https://some-domain.com/some/path/to.json")

        with self.assertRaises(pystac.ExtensionTypeError):
            EOExtension.ext(link)  # type: ignore