def test_filter_coverage(self): polygon = shapely.geometry.Point(0.0, 0.0).buffer(1) ctx = geocontext.AOI(geometry=polygon) scenes = SceneCollection([ Scene(dict(id='foo', geometry=polygon, properties={}), {}), Scene(dict(id='bar', geometry=polygon.buffer(-0.1), properties={}), {}), ]) self.assertEqual(len(scenes.filter_coverage(ctx)), 1)
def test_coverage(self): scene_geometry = shapely.geometry.Point(0.0, 0.0).buffer(1) scene = Scene(dict(id='foo', geometry=scene_geometry, properties={}), {}) # same geometry (as a GeoJSON) self.assertEqual(scene.coverage(scene_geometry.__geo_interface__), 1.0) # geom is larger geom_larger = shapely.geometry.Point(0.0, 0.0).buffer(2) self.assertEqual(scene.coverage(geom_larger), 0.25) # geom is smaller geom_smaller = shapely.geometry.Point(0.0, 0.0).buffer(0.5) self.assertEqual(scene.coverage(geom_smaller), 1.0)
def test_from_id(self): scene_id = "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1" scene, ctx = Scene.from_id(scene_id) self.assertEqual(scene.properties.id, scene_id) self.assertIsInstance(scene.geometry, shapely.geometry.Polygon) self.assertIsInstance(ctx, geocontext.AOI)
def test_load_multiband(self): scene, ctx = Scene.from_id("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr = scene.ndarray("red green blue", ctx.assign(resolution=1000)) self.assertEqual(arr.shape, (3, 239, 235)) self.assertTrue((arr.mask[:, 2, 2]).all()) self.assertFalse((arr.mask[:, 115, 116]).all())
def test_stack(self): scenes = ( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1", ) scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) scenes = SceneCollection(scenes) stack, metas = scenes.stack("nir", ctx, raster_info=True) assert stack.shape == (2, 1, 122, 120) assert (stack.mask[:, 0, 2, 2]).all() assert len(metas) == 2 assert all(len(m["geoTransform"]) == 6 for m in metas) img_stack = scenes.stack("nir red", ctx, bands_axis=-1) assert img_stack.shape == (2, 122, 120, 2) # no_alpha = scenes.stack("nir", mask_alpha=False) # # assert raster not called with alpha once mocks exist no_mask = scenes.stack("nir", ctx, mask_alpha=False, mask_nodata=False) assert not hasattr(no_mask, "mask") assert no_mask.shape == (2, 1, 122, 120) with pytest.raises(NotImplementedError): scenes.stack("nir red", ctx, bands_axis=0) stack_axis_1 = scenes.stack("nir red", ctx, bands_axis=1) assert stack_axis_1.shape == (2, 2, 122, 120)
def test_mosaic_no_alpha(self): scenes = ( "modis:mod11a2:006:meta_MOD11A2.A2017305.h09v05.006.2017314042814_v1", "modis:mod11a2:006:meta_MOD11A2.A2000049.h08v05.006.2015058135046_v1", ) scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) sc = SceneCollection(scenes) no_mask = sc.mosaic(["Clear_sky_days", "Clear_sky_nights"], ctx, mask_nodata=False) assert not hasattr(no_mask, "mask") masked_alt_alpha_band = sc.mosaic( ["Clear_sky_days", "Clear_sky_nights"], ctx, mask_alpha="Clear_sky_nights") assert hasattr(masked_alt_alpha_band, "mask") # errors when alternate alpha band is provided but not available in the scene with pytest.raises(ValueError): sc.mosaic(["Clear_sky_days", "Clear_sky_nights"], ctx, mask_alpha="alt-alpha")
def test_mosaic(self): scenes = ("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1") scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) scenes = SceneCollection(scenes) mosaic, meta = scenes.mosaic("nir", ctx, raster_info=True) self.assertEqual(mosaic.shape, (1, 122, 120)) self.assertTrue((mosaic.mask[:, 2, 2]).all()) self.assertEqual(len(meta["geoTransform"]), 6) img_mosaic = scenes.mosaic("nir red", ctx, bands_axis=-1) self.assertEqual(img_mosaic.shape, (122, 120, 2)) mosaic_with_alpha = scenes.mosaic(["red", "alpha"], ctx) self.assertEqual(mosaic_with_alpha.shape, (2, 122, 120)) mosaic_only_alpha = scenes.mosaic("alpha", ctx) self.assertEqual(mosaic_only_alpha.shape, (1, 122, 120)) self.assertTrue(((mosaic_only_alpha.data == 0) == mosaic_only_alpha.mask).all()) # no_alpha = scenes.mosaic("nir", mask_alpha=False) # # assert raster not called with alpha once mocks exist no_mask = scenes.mosaic("nir", ctx, mask_alpha=False, mask_nodata=False) self.assertFalse(hasattr(no_mask, "mask")) self.assertEqual(no_mask.shape, (1, 122, 120)) with self.assertRaises(ValueError): scenes.mosaic("alpha red", ctx) with self.assertRaises(TypeError): scenes.mosaic("red", ctx, invalid_argument=True)
def test_scenes_bands_dict(self): meta_bands = { "someproduct:red": { "name": "red", "id": "someproduct:red" }, "someproduct:green": { "name": "green", "id": "someproduct:green" }, "someproduct:ndvi": { "name": "ndvi", "id": "someproduct:ndvi" }, "derived:ndvi": { "name": "ndvi", "id": "derived:ndvi" }, } scenes_bands = Scene._scenes_bands_dict(meta_bands) self.assertEqual( set(scenes_bands.keys()), {"red", "green", "ndvi", "derived:ndvi"} ) self.assertEqual(scenes_bands.ndvi, meta_bands["someproduct:ndvi"]) self.assertEqual(scenes_bands["derived:ndvi"], meta_bands["derived:ndvi"])
def test_stack_flatten(self): scenes = ( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", # note: just duplicated "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1", ) scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[2].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) scenes = SceneCollection(scenes) unflattened = scenes.stack("nir", ctx) flattened, metas = scenes.stack("nir", ctx, flatten="properties.id", raster_info=True) assert len(flattened) == 2 assert len(metas) == 2 mosaic = scenes.mosaic("nir", ctx) allflat = scenes.stack("nir", ctx, flatten="properties.product") assert (mosaic == allflat).all() for i, scene in enumerate(scenes): scene.properties.foo = i noflat = scenes.stack("nir", ctx, flatten="properties.foo") assert len(noflat) == len(scenes) assert (noflat == unflattened).all()
def test_stack(self): scenes = ("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1") scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds=overlap.bounds, resolution=600) scenes = SceneCollection(scenes) stack, metas = scenes.stack("nir", ctx, raster_info=True) self.assertEqual(stack.shape, (2, 1, 123, 121)) self.assertTrue((stack.mask[:, 0, 2, 2]).all()) self.assertEqual(len(metas), 2) self.assertTrue(all(len(m["geoTransform"]) == 6 for m in metas)) img_stack = scenes.stack("nir red", ctx, bands_axis=-1) self.assertEqual(img_stack.shape, (2, 123, 121, 2)) # no_alpha = scenes.stack("nir", mask_alpha=False) # # assert raster not called with alpha once mocks exist no_mask = scenes.stack("nir", ctx, mask_alpha=False, mask_nodata=False) self.assertFalse(hasattr(no_mask, "mask")) self.assertEqual(no_mask.shape, (2, 1, 123, 121)) with self.assertRaises(NotImplementedError): scenes.stack("nir red", ctx, bands_axis=0) stack_axis_1 = scenes.stack("nir red", ctx, bands_axis=1) self.assertEqual(stack_axis_1.shape, (2, 2, 123, 121))
def test_bands_to_list(self): self.assertEqual(Scene._bands_to_list("one"), ["one"]) self.assertEqual(Scene._bands_to_list(["one"]), ["one"]) self.assertEqual(Scene._bands_to_list("one two three"), ["one", "two", "three"]) self.assertEqual(Scene._bands_to_list(["one", "two", "three"]), ["one", "two", "three"]) with self.assertRaises(TypeError): Scene._bands_to_list(1) with self.assertRaises(ValueError): Scene._bands_to_list([])
def test_different_band_dtypes(self): scene, ctx = Scene.from_id( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") scene.properties.bands["green"]["dtype"] = "Int16" arr, info = scene.ndarray("red green", ctx.assign(resolution=600), mask_alpha=False) assert arr.dtype.type == np.int32
def test_coverage(self): scene_geometry = shapely.geometry.Point(0.0, 0.0).buffer(1) scene = Scene(dict(id="foo", geometry=scene_geometry, properties={}), {}) # same geometry (as a GeoJSON) assert scene.coverage( scene_geometry.__geo_interface__) == pytest.approx(1.0, abs=1e-6) # geom is larger geom_larger = shapely.geometry.Point(0.0, 0.0).buffer(2) assert scene.coverage(geom_larger) == 0.25 # geom is smaller geom_smaller = shapely.geometry.Point(0.0, 0.0).buffer(0.5) assert scene.coverage(geom_smaller) == 1.0
def test_bands_to_list(self): assert Scene._bands_to_list("one") == ["one"] assert Scene._bands_to_list(["one"]) == ["one"] assert Scene._bands_to_list("one two three") == ["one", "two", "three"] assert Scene._bands_to_list(["one", "two", "three"]) == ["one", "two", "three"] with pytest.raises(TypeError): Scene._bands_to_list(1) with pytest.raises(ValueError): Scene._bands_to_list([])
def test_auto_mask_alpha_true(self): scene, ctx = Scene.from_id( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr = scene.ndarray(["red", "green", "blue"], ctx.assign(resolution=1000), mask_nodata=False) self.assertTrue(hasattr(arr, "mask")) self.assertEqual(arr.shape, (3, 239, 235))
def test_from_id(self): scene_id = "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1" scene, ctx = Scene.from_id(scene_id) self.assertEqual(scene.properties.id, scene_id) self.assertIsInstance(ctx, geocontext.AOI) self.assertEqual(ctx.resolution, 15) self.assertEqual(ctx.crs, "EPSG:32615") self.assertEqual(ctx.bounds, scene.geometry.bounds) self.assertEqual(ctx.geometry, None)
def test_stack_serial(self): scenes = ("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1") scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) scenes = SceneCollection(scenes) stack, metas = scenes.stack("nir", ctx, raster_info=True) self.assertEqual(stack.shape, (2, 1, 122, 120))
def test_auto_mask_alpha_false(self): scene, ctx = Scene.from_id( "modis:mod11a2:006:meta_MOD11A2.A2017305.h09v05.006.2017314042814_v1" ) arr = scene.ndarray(['Clear_sky_days', 'Clear_sky_nights'], ctx.assign(resolution=1000), mask_nodata=False) self.assertFalse(hasattr(arr, "mask")) self.assertEqual(arr.shape, (2, 688, 473))
def test_load_nomask(self): scene, ctx = Scene.from_id( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr = scene.ndarray(["red", "nir"], ctx.assign(resolution=1000), mask_nodata=False, mask_alpha=False) self.assertFalse(hasattr(arr, "mask")) self.assertEqual(arr.shape, (2, 230, 231))
def test_load_one_band(self): scene, ctx = Scene.from_id("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr, info = scene.ndarray("red", ctx.assign(resolution=1000), raster_info=True) self.assertEqual(arr.shape, (1, 239, 235)) self.assertTrue(arr.mask[0, 2, 2]) self.assertFalse(arr.mask[0, 115, 116]) self.assertEqual(len(info["geoTransform"]), 6) with self.assertRaises(TypeError): scene.ndarray("blue", ctx, invalid_argument=True)
def test_mask_missing_band(self): scene, ctx = Scene.from_id( "modis:mod11a2:006:meta_MOD11A2.A2017305.h09v05.006.2017314042814_v1" ) with pytest.raises(ValueError): scene.ndarray( ["Clear_sky_days", "Clear_sky_nights"], ctx.assign(resolution=1000), mask_alpha="missing_band", mask_nodata=False, )
def test_load_multiband_axis_last(self): scene, ctx = Scene.from_id("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr = scene.ndarray("red green blue", ctx.assign(resolution=1000), bands_axis=-1) self.assertEqual(arr.shape, (239, 235, 3)) self.assertTrue((arr.mask[2, 2, :]).all()) self.assertFalse((arr.mask[115, 116, :]).all()) with self.assertRaises(ValueError): arr = scene.ndarray("red green blue", ctx.assign(resolution=1000), bands_axis=3) with self.assertRaises(ValueError): arr = scene.ndarray("red green blue", ctx.assign(resolution=1000), bands_axis=-3)
def test_auto_mask_alpha_false(self): scene, ctx = Scene.from_id( "modis:mod11a2:006:meta_MOD11A2.A2017305.h09v05.006.2017314042814_v1" ) arr = scene.ndarray( ["Clear_sky_days", "Clear_sky_nights"], ctx.assign(resolution=1000), mask_nodata=False, ) assert not hasattr(arr, "mask") assert arr.shape == (2, 688, 473)
def test_different_band_dtypes_fails(self): scene, ctx = Scene.from_id("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") scene.properties.bands = { "red": { "dtype": "UInt16" }, "green": { "dtype": "Int16" } } with self.assertRaises(ValueError): scene.ndarray("red green", ctx)
def with_alpha(self): scene, ctx = Scene.from_id("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr = scene.ndarray(["red", "alpha"], ctx.assign(resolution=1000)) self.assertEqual(arr.shape, (2, 239, 235)) self.assertTrue((arr.mask == (arr.data[1] == 0)).all()) arr = scene.ndarray(["alpha"], ctx.assign(resolution=1000), mask_nodata=False) self.assertEqual(arr.shape, (1, 239, 235)) self.assertTrue((arr.mask == (arr.data == 0)).all()) with self.assertRaises(ValueError): arr = scene.ndarray("alpha red", ctx.assign(resolution=1000))
def test_fails_with_different_dtypes(self): scenes = ("landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1") scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) scenes = SceneCollection(scenes) scenes[0].properties.bands.nir.dtype = "Byte" with self.assertRaises(ValueError): mosaic, meta = scenes.mosaic("nir", ctx) with self.assertRaises(ValueError): stack, meta = scenes.stack("nir", ctx)
def test_coverage(self): scene_geometry = shapely.geometry.mapping( shapely.geometry.Point(0.0, 0.0).buffer(1)) scene = Scene(dict(id='foo', geometry=scene_geometry, properties={}), {}) # same geometry ctx = geocontext.AOI(scene_geometry) self.assertEqual(scene.coverage(ctx), 1.0) # ctx is larger ctx = geocontext.AOI( shapely.geometry.mapping( shapely.geometry.Point(0.0, 0.0).buffer(2))) self.assertEqual(scene.coverage(ctx), 0.25) # ctx is smaller ctx = geocontext.AOI( shapely.geometry.mapping( shapely.geometry.Point(0.0, 0.0).buffer(0.5))) self.assertEqual(scene.coverage(ctx), 1.0)
def test_load_one_band(self): scene, ctx = Scene.from_id( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1") arr, info = scene.ndarray("red", ctx.assign(resolution=1000), raster_info=True) assert arr.shape == (1, 239, 235) assert arr.mask[0, 2, 2] assert not arr.mask[0, 115, 116] assert len(info["geoTransform"]) == 6 with pytest.raises(TypeError): scene.ndarray("blue", ctx, invalid_argument=True)
def test_no_shapely(self): scene_id = "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1" metadata = metadata_client.get(scene_id) bands = metadata_client.get_bands_by_id(scene_id) metadata = { "type": "Feature", "geometry": metadata.pop("geometry"), "id": metadata.pop("id"), "key": metadata.pop("key"), "properties": metadata } scene = Scene(metadata, bands) self.assertIsInstance(scene.geometry, dict) self.assertIs(scene.__geo_interface__, metadata["geometry"])
def test_incompatible_dtypes(self): scenes = ( "landsat:LC08:PRE:TOAR:meta_LC80270312016188_v1", "landsat:LC08:PRE:TOAR:meta_LC80260322016197_v1", ) scenes, ctxs = zip(*[Scene.from_id(scene) for scene in scenes]) overlap = scenes[0].geometry.intersection(scenes[1].geometry) ctx = ctxs[0].assign(geometry=overlap, bounds="update", resolution=600) scenes = SceneCollection(scenes) scenes[0].properties.bands.nir.dtype = "Int16" mosaic = scenes.mosaic("nir", ctx) assert mosaic.dtype.type == np.int32 stack, meta = scenes.stack("nir", ctx) assert stack.dtype.type == np.int32