Example #1
0
    def test_label_classes(self) -> None:
        # Get
        label_item = pystac.Item.from_file(self.label_example_1_uri)
        label_classes = LabelExtension.ext(label_item).label_classes

        self.assertEqual(len(get_opt(label_classes)), 2)
        self.assertEqual(get_opt(label_classes)[1].classes, ["three", "four"])

        # Set
        new_classes = [
            LabelClasses.create(name="label2", classes=["five", "six"]),
            LabelClasses.create(name="label", classes=["seven", "eight"]),
        ]

        label_ext = LabelExtension.ext(label_item)
        label_ext.label_classes = new_classes
        self.assertEqual(
            [
                class_name for lc in label_item.properties["label:classes"]
                for class_name in lc["classes"]
            ],
            ["five", "six", "seven", "eight"],
        )

        self.assertListEqual([lc.name for lc in label_ext.label_classes],
                             ["label2", "label"])

        first_lc = label_ext.label_classes[0]
        self.assertEqual("<ClassObject classes=five,six>", first_lc.__repr__())

        label_item.validate()
Example #2
0
    def test_merge_label_overviews_empty_counts(self) -> None:
        # Right side is empty
        overview_1 = LabelOverview.create(
            property_key="label",
            counts=[
                LabelCount.create(name="water", count=25),
                LabelCount.create(name="land", count=17),
            ],
        )
        overview_2 = LabelOverview.create(
            property_key="label",
            counts=None,
        )

        merged_overview_1 = overview_1.merge_counts(overview_2)
        expected_counts = [c.to_dict() for c in get_opt(overview_1.counts)]
        actual_counts = [
            c.to_dict() for c in get_opt(merged_overview_1.counts)
        ]
        self.assertListEqual(expected_counts, actual_counts)

        # Left side is empty
        merged_overview_2 = overview_2.merge_counts(overview_1)
        expected_counts = [c.to_dict() for c in get_opt(overview_1.counts)]
        actual_counts = [
            c.to_dict() for c in get_opt(merged_overview_2.counts)
        ]
        self.assertEqual(expected_counts, actual_counts)
Example #3
0
    def test_null_datetime(self) -> None:
        item = pystac.Item.from_file(
            TestCases.get_path("data-files/item/sample-item.json"))

        with self.assertRaises(pystac.STACError):
            Item(
                "test",
                geometry=item.geometry,
                bbox=item.bbox,
                datetime=None,
                properties={},
            )

        null_dt_item = Item(
            "test",
            geometry=item.geometry,
            bbox=item.bbox,
            datetime=None,
            properties={
                "start_datetime": datetime_to_str(get_opt(item.datetime)),
                "end_datetime": datetime_to_str(get_opt(item.datetime)),
            },
        )

        null_dt_item.validate()
    def test_common_metadata_providers(self) -> None:
        x = self.ITEM_2.clone()

        providers_dict_list: List[Dict[str, Any]] = [{
            "name":
            "CoolSat",
            "roles": ["producer", "licensor"],
            "url":
            "https://cool-sat.com/",
        }]
        providers_object_list = [
            Provider.from_dict(d) for d in providers_dict_list
        ]

        example_providers_dict_list: List[Dict[str, Any]] = [
            {
                "name": "ExampleProvider_1",
                "roles": ["example_role_1", "example_role_2"],
                "url": "https://exampleprovider1.com/",
            },
            {
                "name": "ExampleProvider_2",
                "roles": ["example_role_1", "example_role_2"],
                "url": "https://exampleprovider2.com/",
            },
        ]
        example_providers_object_list = [
            Provider.from_dict(d) for d in example_providers_dict_list
        ]

        for i in range(len(utils.get_opt(x.common_metadata.providers))):
            p1 = utils.get_opt(x.common_metadata.providers)[i]
            p2 = providers_object_list[i]
            self.assertIsInstance(p1, Provider)
            self.assertIsInstance(p2, Provider)
            self.assertDictEqual(p1.to_dict(), p2.to_dict())

            pd1 = x.properties["providers"][i]
            pd2 = providers_dict_list[i]
            self.assertIsInstance(pd1, dict)
            self.assertIsInstance(pd2, dict)
            self.assertDictEqual(pd1, pd2)

        x.common_metadata.providers = example_providers_object_list

        for i in range(len(x.common_metadata.providers)):
            p1 = x.common_metadata.providers[i]
            p2 = example_providers_object_list[i]
            self.assertIsInstance(p1, Provider)
            self.assertIsInstance(p2, Provider)
            self.assertDictEqual(p1.to_dict(), p2.to_dict())

            pd1 = x.properties["providers"][i]
            pd2 = example_providers_dict_list[i]
            self.assertIsInstance(pd1, dict)
            self.assertIsInstance(pd2, dict)
            self.assertDictEqual(pd1, pd2)
Example #5
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)
Example #6
0
    def test_from_file(self) -> None:
        label_example_1 = Item.from_file(self.label_example_1_uri)

        overviews = get_opt(
            LabelExtension.ext(label_example_1).label_overviews)
        self.assertEqual(len(get_opt(overviews[0].counts)), 2)
        label_example_1.validate()

        label_example_2 = Item.from_file(self.label_example_2_uri)
        overviews2 = get_opt(
            LabelExtension.ext(label_example_2).label_overviews)
        self.assertEqual(len(get_opt(overviews2[0].counts)), 2)

        label_example_2.validate()
Example #7
0
    def statistics(self) -> Optional[Statistics]:
        """Get or sets the average spatial resolution (in meters) of the pixels in the band.

        Returns:
            [Statistics]
        """
        return Statistics.from_dict(get_opt(self.properties.get("statistics")))
Example #8
0
    def test_wkt2(self) -> None:
        proj_item = pystac.Item.from_file(self.example_uri)

        # Get
        self.assertIn("proj:wkt2", proj_item.properties)
        proj_wkt2 = ProjectionExtension.ext(proj_item).wkt2
        self.assertEqual(proj_wkt2, proj_item.properties["proj:wkt2"])

        # Set
        ProjectionExtension.ext(proj_item).wkt2 = WKT2
        self.assertEqual(WKT2, proj_item.properties["proj:wkt2"])

        # Get from Asset
        asset_no_prop = proj_item.assets["B1"]
        asset_prop = proj_item.assets["B8"]
        self.assertEqual(
            ProjectionExtension.ext(asset_no_prop).wkt2,
            ProjectionExtension.ext(proj_item).wkt2,
        )
        self.assertTrue(
            "TEST_TEXT" in get_opt(ProjectionExtension.ext(asset_prop).wkt2)
        )

        # Set to Asset
        asset_value = "TEST TEXT 2"
        ProjectionExtension.ext(asset_no_prop).wkt2 = asset_value
        self.assertNotEqual(
            ProjectionExtension.ext(asset_no_prop).wkt2,
            ProjectionExtension.ext(proj_item).wkt2,
        )
        self.assertEqual(ProjectionExtension.ext(asset_no_prop).wkt2, asset_value)

        # Validate
        proj_item.validate()
Example #9
0
    def test_merge_label_overviews(self) -> None:

        overview_1 = LabelOverview.create(
            property_key="label",
            counts=[
                LabelCount.create(name="water", count=25),
                LabelCount.create(name="land", count=17),
            ],
        )
        overview_2 = LabelOverview.create(
            property_key="label",
            counts=[
                LabelCount.create(name="water", count=10),
                LabelCount.create(name="unknown", count=4),
            ],
        )
        merged_overview = overview_1.merge_counts(overview_2)

        merged_counts = get_opt(merged_overview.counts)

        water_count = next(c for c in merged_counts if c.name == "water")
        land_count = next(c for c in merged_counts if c.name == "land")
        unknown_count = next(c for c in merged_counts if c.name == "unknown")

        self.assertEqual(35, water_count.count)
        self.assertEqual(17, land_count.count)
        self.assertEqual(4, unknown_count.count)
Example #10
0
    def histogram(self) -> Optional[Histogram]:
        """Get or sets the histogram distribution information of the pixels values in the band

        Returns:
            [Histogram]
        """
        return Histogram.from_dict(get_opt(self.properties.get("histogram")))
Example #11
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")
Example #12
0
    def test_validate_error_contains_href(self) -> None:
        # Test that the exception message contains the HREF of the object if available.
        cat = TestCases.test_case_1()
        item = cat.get_item("area-1-1-labels", recursive=True)
        assert item is not None
        assert item.get_self_href() is not None

        item.geometry = {"type": "INVALID"}

        with self.assertRaises(pystac.STACValidationError):
            try:
                item.validate()
            except pystac.STACValidationError as e:
                self.assertTrue(get_opt(item.get_self_href()) in str(e))
                raise e
Example #13
0
    def test_merge(self) -> None:
        cat1 = create_catalog(1, include_href=False)
        cat2 = create_catalog(2)
        cat3 = create_catalog(3, include_href=False)
        cat4 = create_catalog(4)

        identical_cat1 = create_catalog(1, include_href=False)
        identical_cat2 = create_catalog(2)

        cached_ids_1: Dict[str, Any] = {cat1.id: cat1}
        cached_hrefs_1: Dict[str, Any] = {get_opt(cat2.get_self_href()): cat2}
        cached_ids_2: Dict[str, Any] = {cat3.id: cat3, cat1.id: identical_cat1}
        cached_hrefs_2: Dict[str, Any] = {
            get_opt(cat4.get_self_href()): cat4,
            get_opt(cat2.get_self_href()): identical_cat2,
        }
        cache1 = ResolvedObjectCollectionCache(
            ResolvedObjectCache(), cached_ids=cached_ids_1, cached_hrefs=cached_hrefs_1
        )
        cache2 = ResolvedObjectCollectionCache(
            ResolvedObjectCache(), cached_ids=cached_ids_2, cached_hrefs=cached_hrefs_2
        )

        merged = ResolvedObjectCollectionCache.merge(
            ResolvedObjectCache(), cache1, cache2
        )

        self.assertEqual(
            set(merged.cached_ids.keys()), set([cat.id for cat in [cat1, cat3]])
        )
        self.assertIs(merged.get_by_id(cat1.id), cat1)
        self.assertEqual(
            set(merged.cached_hrefs.keys()),
            set([cat.get_self_href() for cat in [cat2, cat4]]),
        )
        self.assertIs(merged.get_by_href(get_opt(cat2.get_self_href())), cat2)
Example #14
0
    def test_published(self) -> None:
        timestamps_item = pystac.Item.from_file(self.example_uri)

        # Get
        self.assertIn("published", timestamps_item.properties)
        timestamps_published = TimestampsExtension.ext(
            timestamps_item).published
        self.assertIsInstance(timestamps_published, datetime)
        self.assertEqual(
            datetime_to_str(get_opt(timestamps_published)),
            timestamps_item.properties["published"],
        )

        # Set
        TimestampsExtension.ext(
            timestamps_item).published = self.sample_datetime
        self.assertEqual(self.sample_datetime_str,
                         timestamps_item.properties["published"])

        # Get from Asset
        asset_no_prop = timestamps_item.assets["red"]
        asset_prop = timestamps_item.assets["blue"]
        self.assertEqual(
            TimestampsExtension.ext(asset_no_prop).published,
            TimestampsExtension.ext(timestamps_item).published,
        )
        self.assertEqual(
            TimestampsExtension.ext(asset_prop).published,
            str_to_datetime("2018-11-02T00:00:00Z"),
        )

        # # Set to Asset
        asset_value = str_to_datetime("2019-02-02T00:00:00Z")
        TimestampsExtension.ext(asset_no_prop).published = asset_value
        self.assertNotEqual(
            TimestampsExtension.ext(asset_no_prop).published,
            TimestampsExtension.ext(timestamps_item).published,
        )
        self.assertEqual(
            TimestampsExtension.ext(asset_no_prop).published, asset_value)

        # Validate
        timestamps_item.validate()
Example #15
0
    def test_validate_all(self) -> None:
        for test_case in TestCases.all_test_catalogs():
            catalog_href = test_case.get_self_href()
            if catalog_href is not None:
                stac_dict = pystac.StacIO.default().read_json(catalog_href)

                pystac.validation.validate_all(stac_dict, catalog_href)

        # Modify a 0.8.1 collection in a catalog to be invalid with a
        # since-renamed extension and make sure it catches the validation error.

        with tempfile.TemporaryDirectory() as tmp_dir:
            dst_dir = os.path.join(tmp_dir, "catalog")
            # Copy test case 7 to the temporary directory
            catalog_href = get_opt(TestCases.test_case_7().get_self_href())
            shutil.copytree(os.path.dirname(catalog_href), dst_dir)

            new_cat_href = os.path.join(dst_dir, "catalog.json")

            # Make sure it's valid before modification
            pystac.validation.validate_all(
                pystac.StacIO.default().read_json(new_cat_href), new_cat_href)

            # Modify a contained collection to add an extension for which the
            # collection is invalid.
            with open(os.path.join(dst_dir, "acc/collection.json"),
                      encoding="utf-8") as f:
                col = json.load(f)
            col["stac_extensions"] = ["asset"]
            with open(os.path.join(dst_dir, "acc/collection.json"),
                      "w",
                      encoding="utf-8") as f:
                json.dump(col, f)

            stac_dict = pystac.StacIO.default().read_json(new_cat_href)

            with self.assertRaises(pystac.STACValidationError):
                pystac.validation.validate_all(stac_dict, new_cat_href)
Example #16
0
    def test_label_overviews(self) -> None:
        # Get
        label_item = pystac.Item.from_file(self.label_example_1_uri)
        label_ext = LabelExtension.ext(label_item)
        label_overviews = get_opt(label_ext.label_overviews)

        label_item2 = pystac.Item.from_file(self.label_example_2_uri)
        label_ext2 = LabelExtension.ext(label_item2)
        label_overviews2 = get_opt(label_ext2.label_overviews)

        self.assertEqual(len(label_overviews), 2)
        self.assertEqual(label_overviews[1].property_key, "label-reg")
        self.assertEqual(label_overviews2[1].property_key, None)  # Raster

        label_counts = get_opt(label_overviews[0].counts)
        self.assertEqual(label_counts[1].count, 17)
        first_overview_counts = get_opt(label_ext.label_overviews)[0].counts
        assert first_overview_counts is not None
        first_overview_counts[1].count = 18
        self.assertEqual(
            label_item.properties["label:overviews"][0]["counts"][1]["count"],
            18)
        self.assertEqual(first_overview_counts[1].name, "two")

        label_statistics = get_opt(label_overviews[1].statistics)
        self.assertEqual(label_statistics[0].name, "mean")
        second_overview_statistics = get_opt(
            label_ext.label_overviews)[1].statistics
        assert second_overview_statistics is not None
        second_overview_statistics[0].name = "avg"
        self.assertEqual(
            label_item.properties["label:overviews"][1]["statistics"][0]
            ["name"], "avg")

        # Set
        new_overviews = [
            LabelOverview.create(
                property_key="label2",
                counts=[
                    LabelCount.create(name="one", count=1),
                    LabelCount.create(name="two", count=1),
                ],
            ),
            LabelOverview.create(
                property_key="label-reg",
                statistics=[
                    LabelStatistics.create(name="min", value=0.1),
                    LabelStatistics.create(name="max", value=1.0),
                ],
            ),
        ]

        label_ext.label_overviews = new_overviews
        self.assertEqual(
            [(count["name"], count["count"])
             for count in label_item.properties["label:overviews"][0]["counts"]
             ],
            [("one", 1), ("two", 1)],
        )

        self.assertEqual(
            [(count["name"], count["value"]) for count in
             label_item.properties["label:overviews"][1]["statistics"]],
            [("min", 0.1), ("max", 1.0)],
        )

        label_item.validate()
Example #17
0
    def test_asset_bands(self) -> None:
        item = pystac.Item.from_file(self.PLANET_EXAMPLE_URI)
        item2 = pystac.Item.from_file(self.SENTINEL2_EXAMPLE_URI)

        # Get
        data_asset = item.assets["data"]
        asset_bands = RasterExtension.ext(data_asset).bands
        assert asset_bands is not None
        self.assertEqual(len(asset_bands), 4)
        self.assertEqual(asset_bands[0].nodata, 0)
        self.assertEqual(asset_bands[0].sampling, Sampling.AREA)
        self.assertEqual(asset_bands[0].unit, "W⋅sr−1⋅m−2⋅nm−1")
        self.assertEqual(asset_bands[0].data_type, DataType.UINT16)
        self.assertEqual(asset_bands[0].scale, 0.01)
        self.assertEqual(asset_bands[0].offset, 0)
        self.assertEqual(asset_bands[0].spatial_resolution, 3)

        band0_stats = asset_bands[0].statistics
        assert band0_stats is not None
        self.assertEqual(band0_stats.minimum, 1962)
        self.assertEqual(band0_stats.maximum, 32925)
        self.assertEqual(band0_stats.mean, 8498.9400644319)
        self.assertEqual(band0_stats.stddev, 5056.1292002722)
        self.assertEqual(band0_stats.valid_percent, 61.09)

        band0_hist = asset_bands[0].histogram
        assert band0_hist is not None
        self.assertEqual(band0_hist.count, 256)
        self.assertEqual(band0_hist.min, 1901.288235294118)
        self.assertEqual(band0_hist.max, 32985.71176470588)
        self.assertEqual(len(band0_hist.buckets), band0_hist.count)

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

        b09_asset = item2.assets["B09"]
        b09_bands = RasterExtension.ext(b09_asset).bands
        assert b09_bands is not None
        self.assertEqual(b09_bands[0].nodata, "nan")

        # Set
        b2_asset = item2.assets["B02"]
        self.assertEqual(
            get_opt(
                get_opt(RasterExtension.ext(b2_asset).bands)
                [0].statistics).maximum,
            19264,
        )
        b1_asset = item2.assets["B01"]
        RasterExtension.ext(b2_asset).bands = RasterExtension.ext(
            b1_asset).bands

        new_b2_asset_bands = RasterExtension.ext(item2.assets["B02"]).bands

        self.assertEqual(
            get_opt(get_opt(new_b2_asset_bands)[0].statistics).maximum, 20567)

        new_b2_asset_band0 = get_opt(new_b2_asset_bands)[0]
        new_b2_asset_band0.nodata = NoDataStrings.INF

        item2.validate()

        # Check adding a new asset
        new_stats = [
            Statistics.create(minimum=0,
                              maximum=10000,
                              mean=5000,
                              stddev=10,
                              valid_percent=88),
            Statistics.create(minimum=-1,
                              maximum=1,
                              mean=0,
                              stddev=1,
                              valid_percent=100),
            Statistics.create(minimum=1,
                              maximum=255,
                              mean=200,
                              stddev=3,
                              valid_percent=100),
        ]
        # new_histograms = []
        with open(self.GDALINFO_EXAMPLE_URI) as gdaljson_file:
            gdaljson_data = json.load(gdaljson_file)
            new_histograms = list(
                map(
                    lambda band: Histogram.from_dict(band["histogram"]),
                    gdaljson_data["bands"],
                ))
        new_bands = [
            RasterBand.create(
                nodata=1,
                unit="test1",
                statistics=new_stats[0],
                histogram=new_histograms[0],
            ),
            RasterBand.create(
                nodata=2,
                unit="test2",
                statistics=new_stats[1],
                histogram=new_histograms[1],
            ),
            RasterBand.create(
                nodata=NoDataStrings.NINF,
                unit="test3",
                statistics=new_stats[2],
                histogram=new_histograms[2],
            ),
        ]
        asset = pystac.Asset(href="some/path.tif",
                             media_type=pystac.MediaType.GEOTIFF)
        RasterExtension.ext(asset).bands = new_bands
        item.add_asset("test", asset)

        self.assertEqual(len(item.assets["test"].extra_fields["raster:bands"]),
                         3)
        self.assertEqual(
            item.assets["test"].extra_fields["raster:bands"][1]["statistics"]
            ["minimum"],
            -1,
        )
        self.assertEqual(
            item.assets["test"].extra_fields["raster:bands"][1]["histogram"]
            ["min"],
            3848.354901960784,
        )
        self.assertEqual(
            item.assets["test"].extra_fields["raster:bands"][2]["nodata"],
            "-inf")

        for s in new_stats:
            s.minimum = None
            s.maximum = None
            s.mean = None
            s.stddev = None
            s.valid_percent = None
            self.assertEqual(len(s.properties), 0)

        for b in new_bands:
            b.bits_per_sample = None
            b.data_type = None
            b.histogram = None
            b.nodata = None
            b.sampling = None
            b.scale = None
            b.spatial_resolution = None
            b.statistics = None
            b.unit = None
            b.offset = None
            self.assertEqual(len(b.properties), 0)

        new_stats[2].apply(minimum=0,
                           maximum=10000,
                           mean=5000,
                           stddev=10,
                           valid_percent=88)
        new_stats[1].apply(minimum=-1,
                           maximum=1,
                           mean=0,
                           stddev=1,
                           valid_percent=100)
        new_stats[0].apply(minimum=1,
                           maximum=255,
                           mean=200,
                           stddev=3,
                           valid_percent=100)
        new_bands[2].apply(
            nodata=1,
            unit="test1",
            statistics=new_stats[2],
            histogram=new_histograms[0],
        )
        new_bands[1].apply(
            nodata=2,
            unit="test2",
            statistics=new_stats[1],
            histogram=new_histograms[1],
        )
        new_bands[0].apply(
            nodata=NoDataStrings.NAN,
            unit="test3",
            statistics=new_stats[0],
            histogram=new_histograms[2],
        )
        RasterExtension.ext(item.assets["test"]).apply(new_bands)
        self.assertEqual(
            item.assets["test"].extra_fields["raster:bands"][0]["statistics"]
            ["minimum"],
            1,
        )
        self.assertEqual(
            item.assets["test"].extra_fields["raster:bands"][0]["nodata"],
            "nan")