class TestSample(TestCase): def setUp(self) -> None: predictors = [nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7] self.stack = Raster(predictors) self.strata = Raster(nc.strata) def tearDown(self) -> None: self.stack.close() self.strata.close() def test_sample_strata(self): # extract using a strata raster and returning two arrays size = 100 categories = self.strata.read(masked=True).flatten() categories = categories[~categories.mask] n_categories = np.unique(categories).shape[0] n_samples = size * n_categories X, xy = self.stack.sample(size=size, strata=self.strata, return_array=True) self.assertEqual(X.shape, (n_samples, 6)) self.assertEqual(xy.shape, (n_samples, 2)) # extract using a strata raster and returning a dataframe samples = self.stack.sample(size=size, strata=self.strata, return_array=False) self.assertEqual(samples.shape, (n_samples, 7)) def test_sample_no_strata(self): size = 100 X, xy = self.stack.sample(size=size, return_array=True) self.assertEqual(X.shape, (size, 6)) self.assertEqual(xy.shape, (size, 2)) samples = self.stack.sample(size=size, return_array=False) self.assertEqual(samples.shape, (size, 7))
def test_append_with_copy(self): """Same tests as above but create a new Raster rather than append in place """ # append another Raster containing a single layer with identical name stack = Raster(self.predictors) band7_mean = stack["lsat7_2000_70"].read(masked=True).mean() result = stack.append(Raster(nc.band7), in_place=False) # check that original is untouched self.assertEqual(stack.count, 6) # check that result contains appended raster self.assertEqual(list(result.names)[5], "lsat7_2000_70_1") self.assertEqual(list(result.names)[-1], "lsat7_2000_70_2") # check that band 7 stats are the same after appending self.assertEqual( result.lsat7_2000_70_1.read(masked=True).mean(), result.lsat7_2000_70_2.read(masked=True).mean(), band7_mean, ) # append a multiband raster result = stack.append(Raster(nc.multiband), in_place=False) self.assertEqual(list(result.names)[6], "landsat_multiband_1") stack.close() # append multiple rasters stack = Raster(self.predictors) new_stack = stack.append( [Raster(nc.band5), Raster(nc.band7)], in_place=False) self.assertEqual(new_stack.count, 8)
class TestToCrs(TestCase): def setUp(self) -> None: # inputs self.predictors = [ nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7 ] self.stack = Raster(self.predictors) training_py = gpd.read_file(nc.polygons) self.crop_bounds = training_py.loc[0, "geometry"].bounds # outputs self.cropped = None def tearDown(self) -> None: self.stack.close() self.cropped.close() def test_crop_defaults(self): self.cropped = self.stack.crop(self.crop_bounds) # check raster object self.assertIsInstance(self.cropped, Raster) self.assertEqual(self.cropped.count, self.stack.count) self.assertEqual(self.cropped.read(masked=True).count(), 1440) # test nodata value is recognized self.assertEqual(self.cropped.read(masked=True).min(), 35.0) self.assertEqual(self.cropped.read(masked=True).max(), 168.0) def test_crop_in_memory(self): self.cropped = self.stack.crop(self.crop_bounds, in_memory=True) self.assertIsInstance(self.cropped, Raster)
class TestPlotting(TestCase): def setUp(self) -> None: self.predictors = [ nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7 ] self.stack = Raster(self.predictors) self.stack_single = Raster(self.predictors[0]) def tearDown(self) -> None: self.stack.close() self.stack_single.close() def test_plotting_raster(self): # test basic raster matrix plot p = self.stack.plot() self.assertIsInstance(p, np.ndarray) # test with arguments p = self.stack.plot( cmap="plasma", norm=mpl.colors.Normalize(vmin=10, vmax=100), title_fontsize=10, label_fontsize=10, names=["band1", "band2", "band3", "band4", "band5", "band7"], figsize=(10, 5), legend_kwds={"orientation": "horizontal"}) self.assertIsInstance(p, np.ndarray) def test_plotting_single(self): p = self.stack_single.plot(legend_kwds={ "orientation": "horizontal", "fraction": 0.04 }) self.assertIsInstance(p, mpl.axes.Subplot)
def test_append_inplace(self): """Append another Raster containing a single layer with identical name This test should cause the Raster object to automatically rename the duplicated names as "lsat7_2000_70_1", "lsat7_2000_70_2", etc. Appending a multi-band raster should result in a new layer with the multi-band name "landsat_multiband_1", "landsat_multiband_2", etc. A list of Rasters can be passed to append() to append multiple rasters """ # append a single band raster with the same name stack = Raster(self.predictors) band7_mean = stack["lsat7_2000_70"].read(masked=True).mean() stack.append(Raster(nc.band7), in_place=True) self.assertEqual(list(stack.names)[5], "lsat7_2000_70_1") self.assertEqual(list(stack.names)[-1], "lsat7_2000_70_2") self.assertEqual( stack.lsat7_2000_70_1.read(masked=True).mean(), stack.lsat7_2000_70_2.read(masked=True).mean(), band7_mean, ) # append a multiband raster stack = Raster(self.predictors) stack.append(Raster(nc.multiband), in_place=True) self.assertEqual(list(stack.names)[6], "landsat_multiband_1") stack.close() # append multiple rasters stack = Raster(self.predictors) stack.append([Raster(nc.band5), Raster(nc.band7)], in_place=True) self.assertEqual(stack.count, 8)
def test_subset_multiple_layers(self): stack = Raster(self.predictors + [nc.multiband]) # Subset multiple layers using a slice of index positions # - returns a Raster object self.assertIsInstance(stack.iloc[0:2], Raster) # Subset multiple layers using a list of index positions # - returns a Raster object self.assertIsInstance(stack.iloc[[0, 1, 2]], Raster) # Subset multiple layers using a list of labels # - returns a Raster object subset_raster = stack[["lsat7_2000_10", "lsat7_2000_70"]] self.assertIsInstance(subset_raster, Raster) self.assertListEqual(list(subset_raster.names), ["lsat7_2000_10", "lsat7_2000_70"]) # Check that label and integer subset return the same layers self.assertListEqual( list(stack.iloc[0:3].names), list(stack[["lsat7_2000_10", "lsat7_2000_20", "lsat7_2000_30"]].names), ) stack.close()
class TestCalc(TestCase): def setUp(self) -> None: predictors = [nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7] self.stack = Raster(predictors) self.result = None def tearDown(self) -> None: self.stack.close() self.result.close() self.stack = None self.result = None def test_calc_with_2d_output(self): def compute_outputs_2d_array(arr): return arr[0, :, :] + arr[1, :, :] self.result = self.stack.apply(compute_outputs_2d_array) self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, 1) self.assertEqual(self.result.read(masked=True).count(), 183418) def test_calc_with_2d_output_coerce_dtype(self): def compute_outputs_2d_array(arr): return arr[0, :, :] + arr[1, :, :] self.result = self.stack.apply(compute_outputs_2d_array, dtype=np.int16) self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, 1) self.assertEqual(self.result.read(masked=True).count(), 183418) def test_calc_with_3d_output(self): def compute_outputs_3d_array(arr): arr[0, :, :] = arr[0, :, :] + arr[1, ::] return arr self.result = self.stack.apply(compute_outputs_3d_array) self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, 6) self.assertEqual(self.result.read(masked=True).count(), 1052182) def test_calc_with_multiprocessing(self): def compute_outputs_2d_array(arr): return arr[0, :, :] + arr[1, :, :] self.result = self.stack.apply(compute_outputs_2d_array) self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, 1) self.assertEqual(self.result.read(masked=True).count(), 183418) def test_calc_in_memory(self): def compute_outputs_2d_array(arr): return arr[0, :, :] + arr[1, :, :] self.result = self.stack.apply(compute_outputs_2d_array, in_memory=True) self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, 1) self.assertEqual(self.result.read(masked=True).count(), 183418)
class TestIntersect(TestCase): def setUp(self) -> None: # inputs self.predictors = [nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7] self.stack = Raster(self.predictors) # test results self.result = None def tearDown(self) -> None: self.stack.close() self.result.close() def test_intersect_defaults(self): self.result = self.stack.intersect() # check raster object self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, self.stack.count) self.assertEqual(self.result.read(masked=True).count(), 810552) # test nodata value is recognized self.assertEqual(self.result.read(masked=True).min(), 1.0) self.assertEqual(self.result.read(masked=True).max(), 255.0) def test_intersect_custom_dtype(self): self.result = self.stack.intersect(dtype=np.int16) # check raster object self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, self.stack.count) self.assertEqual(self.result.read(masked=True).count(), 810552) # test nodata value is recognized self.assertEqual(self.result.read(masked=True).min(), 1) self.assertEqual(self.result.read(masked=True).max(), 255) def test_intersect_custom_nodata(self): self.result = self.stack.intersect(dtype=np.int16, nodata=-999) # check raster object self.assertIsInstance(self.result, Raster) self.assertEqual(self.result.count, self.stack.count) self.assertEqual(self.result.read(masked=True).count(), 810552) # test nodata value is recognized self.assertEqual(self.result.read(masked=True).min(), 1) self.assertEqual(self.result.read(masked=True).max(), 255) def test_intersect_in_memory(self): self.result = self.stack.intersect(in_memory=True) # check raster object self.assertIsInstance(self.result, Raster)
def test_drop_inplace(self): stack = Raster(self.predictors) stack.drop(labels="lsat7_2000_50", in_place=True) # check that Raster object is returned self.assertIsInstance(stack, Raster) # check that RasterLayer has been dropped self.assertEqual(stack.count, 5) self.assertNotIn("lsat7_2000_50", stack.names) stack.close()
class TestToCrs(TestCase): def setUp(self) -> None: # test inputs predictors = [ nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7 ] self.stack = Raster(predictors) # test results self.stack_prj = None def tearDown(self) -> None: self.stack.close() self.stack_prj.close() def test_to_crs_defaults(self): self.stack_prj = self.stack.to_crs({"init": "EPSG:4326"}) # check raster object self.assertIsInstance(self.stack_prj, Raster) self.assertEqual(self.stack_prj.count, self.stack.count) self.assertEqual(self.stack_prj.read(masked=True).count(), 1012061) # test nodata value is recognized self.assertEqual( self.stack_prj.read(masked=True).min(), self.stack.read(masked=True).min()) self.assertEqual( self.stack_prj.read(masked=True).max(), self.stack.read(masked=True).max()) def test_to_crs_custom_nodata(self): self.stack_prj = self.stack.to_crs({"init": "EPSG:4326"}, nodata=-999) # check raster object self.assertIsInstance(self.stack_prj, Raster) self.assertEqual(self.stack_prj.count, self.stack.count) self.assertEqual(self.stack_prj.read(masked=True).count(), 1012061) # test nodata value is recognized self.assertEqual( self.stack_prj.read(masked=True).min(), self.stack.read(masked=True).min()) self.assertEqual( self.stack_prj.read(masked=True).max(), self.stack.read(masked=True).max()) def test_to_crs_in_memory(self): self.stack_prj = self.stack.to_crs({"init": "EPSG:4326"}, in_memory=True) # check raster object self.assertIsInstance(self.stack_prj, Raster)
def test_drop_with_copy(self): stack = Raster(self.predictors) names = stack.names result = stack.drop(labels="lsat7_2000_50", in_place=False) # check that Raster object is returned self.assertIsInstance(result, Raster) # check that RasterLayer has been dropped self.assertEqual(result.count, 5) self.assertNotIn("lsat7_2000_50", result.names) # check that original raster is unaffected self.assertEqual(stack.count, 6) self.assertEqual(stack.names, names) stack.close() result.close()
def test_indexing(self): stack = Raster(self.predictors + [nc.multiband]) # replace band 1 with band 7 band7_mean = stack["lsat7_2000_70"].read(masked=True).mean() stack.iloc[0] = Raster(nc.band7).iloc[0] self.assertEqual(stack.iloc[0].read(masked=True).mean(), band7_mean) self.assertEqual(stack["lsat7_2000_10"].read(masked=True).mean(), band7_mean) self.assertEqual(stack["lsat7_2000_10"].read(masked=True).mean(), band7_mean) self.assertEqual( stack.lsat7_2000_10.read(masked=True).mean(), band7_mean) stack.close()
def test_append_inplace(self): # append another Raster containing a single layer with identical name stack = Raster(self.predictors) band7_mean = stack["lsat7_2000_70"].read(masked=True).mean() stack.append(Raster(nc.band7), in_place=True) self.assertEqual(stack.names[5], "lsat7_2000_70_1") self.assertEqual(stack.names[-1], "lsat7_2000_70_2") self.assertEqual( stack.lsat7_2000_70_1.read(masked=True).mean(), stack.lsat7_2000_70_2.read(masked=True).mean(), band7_mean, ) # append a multiband raster stack = Raster(self.predictors) stack.append(Raster(nc.multiband), in_place=True) self.assertEqual(stack.names[6], "landsat_multiband_1") stack.close()
def test_subset_single_layer(self): stack = Raster(self.predictors + [nc.multiband]) # Subset a single layer using an index position - returns a RasterLayer self.assertIsInstance(stack.iloc[0], RasterLayer) # Subset a single layer using a label - returns a RasterLayer self.assertIsInstance(stack["lsat7_2000_10"], RasterLayer) # Subset a single layer using an attribute - returns a RasterLayer self.assertIsInstance(stack.lsat7_2000_10, RasterLayer) # Check that the raster values are the same as the original values # after subsetting self.assertEqual( stack.lsat7_2000_10.read(masked=True).mean(), 80.56715262406088) self.assertEqual( stack.lsat7_2000_70.read(masked=True).mean(), 59.17773813401238) stack.close()
class TestAlter(TestCase): def setUp(self) -> None: predictors = [ nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7 ] self.stack = Raster(predictors) points = gpd.read_file(nc.points) data = self.stack.extract_vector(points) self.data = data.dropna() def tearDown(self) -> None: self.stack.close() def test_alter(self): scaler = StandardScaler() scaler.fit(self.data.drop(columns=["geometry"]).values) out = self.stack.alter(scaler) self.assertIsInstance(out, Raster) self.assertEqual(out.shape, self.stack.shape)
def test_naming(self): stack = Raster(self.predictors + [nc.multiband]) # check unique naming when stacking multiband raster self.assertEqual(stack.count, 11) expected_names = [ "lsat7_2000_10", "lsat7_2000_20", "lsat7_2000_30", "lsat7_2000_40", "lsat7_2000_50", "lsat7_2000_70", "landsat_multiband_1", "landsat_multiband_2", "landsat_multiband_3", "landsat_multiband_4", "landsat_multiband_5", ] self.assertListEqual(list(stack.names), expected_names) stack.close()
def test_append_with_copy(self): # append another Raster containing a single layer with identical name stack = Raster(self.predictors) band7_mean = stack["lsat7_2000_70"].read(masked=True).mean() result = stack.append(Raster(nc.band7), in_place=False) # check that original is untouched self.assertEqual(stack.count, 6) # check that result contains appended raster self.assertEqual(result.names[5], "lsat7_2000_70_1") self.assertEqual(result.names[-1], "lsat7_2000_70_2") # check that band 7 stats are the same after appending self.assertEqual( result.lsat7_2000_70_1.read(masked=True).mean(), result.lsat7_2000_70_2.read(masked=True).mean(), band7_mean, ) # append a multiband raster result = stack.append(Raster(nc.multiband), in_place=False) self.assertEqual(result.names[6], "landsat_multiband_1") stack.close()
class TestMask(TestCase): def setUp(self) -> None: # test inputs training_py = gpd.read_file(nc.polygons) self.mask_py = training_py.iloc[0:1, :] predictors = [ nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7 ] self.stack = Raster(predictors) # test results self.masked_object = None def tearDown(self) -> None: self.stack.close() self.masked_object.close() def test_mask_defaults(self): self.masked_object = self.stack.mask(self.mask_py) # check raster object self.assertIsInstance(self.masked_object, Raster) self.assertEqual(self.masked_object.count, self.stack.count) self.assertEqual(self.masked_object.read(masked=True).count(), 738) # test nodata value is recognized self.assertEqual(self.masked_object.read(masked=True).min(), 38.0) self.assertEqual(self.masked_object.read(masked=True).max(), 168.0) def test_mask_inverted(self): self.masked_object = self.stack.mask(self.mask_py, invert=True) # check raster object self.assertIsInstance(self.masked_object, Raster) self.assertEqual(self.masked_object.count, self.stack.count) self.assertEqual(self.masked_object.read(masked=True).count(), 1051444) # test nodata value is recognized self.assertEqual(self.masked_object.read(masked=True).min(), 1.0) self.assertEqual(self.masked_object.read(masked=True).max(), 255.0) def test_mask_custom_dtype(self): self.masked_object = self.stack.mask(self.mask_py, dtype=np.int16) # check raster object self.assertIsInstance(self.masked_object, Raster) self.assertEqual(self.masked_object.count, self.stack.count) self.assertEqual(self.masked_object.read(masked=True).count(), 738) # test nodata value is recognized self.assertEqual(self.masked_object.read(masked=True).min(), 38) self.assertEqual(self.masked_object.read(masked=True).max(), 168) def test_mask_custom_nodata(self): self.masked_object = self.stack.mask(self.mask_py, nodata=-99999) # check raster object self.assertIsInstance(self.masked_object, Raster) self.assertEqual(self.masked_object.count, self.stack.count) self.assertEqual(self.masked_object.read(masked=True).count(), 738) # test nodata value is recognized self.assertEqual(self.masked_object.read(masked=True).min(), 38.0) self.assertEqual(self.masked_object.read(masked=True).max(), 168.0) def test_mask_in_memory(self): self.masked_object = self.stack.mask(self.mask_py, in_memory=True) # check raster object self.assertIsInstance(self.masked_object, Raster)
class TestExtract(TestCase): def setUp(self) -> None: self.predictors = [ nc.band1, nc.band2, nc.band3, nc.band4, nc.band5, nc.band7 ] self.extracted_grass = pd.read_table(nc.extracted_pixels, delimiter=" ") self.stack = Raster(self.predictors) def tearDown(self) -> None: self.stack.close() def test_extract_points(self): training_pt = geopandas.read_file(nc.points) # check that extracted training data as a DataFrame match known values df = self.stack.extract_vector(gdf=training_pt) df = df.dropna() training_pt = training_pt.dropna() self.assertTrue( (df["lsat7_2000_10"].values == training_pt["b1"].values).all()) self.assertTrue( (df["lsat7_2000_20"].values == training_pt["b2"].values).all()) self.assertTrue( (df["lsat7_2000_30"].values == training_pt["b3"].values).all()) self.assertTrue( (df["lsat7_2000_40"].values == training_pt["b4"].values).all()) self.assertTrue( (df["lsat7_2000_50"].values == training_pt["b5"].values).all()) self.assertTrue( (df["lsat7_2000_70"].values == training_pt["b7"].values).all()) def test_extract_polygons(self): # extract training data from polygons training_py = geopandas.read_file(nc.polygons) df = self.stack.extract_vector(gdf=training_py) df = df.dropna() df = df.merge( right=training_py.loc[:, ("id", "label")], left_on="geometry_idx", right_on="index", right_index=True, ) # compare to extracted data using GRASS GIS self.assertEqual(df.shape[0], self.extracted_grass.shape[0]) self.assertAlmostEqual(df["lsat7_2000_10"].mean(), self.extracted_grass["b1"].mean(), places=2) self.assertAlmostEqual(df["lsat7_2000_20"].mean(), self.extracted_grass["b2"].mean(), places=2) self.assertAlmostEqual(df["lsat7_2000_30"].mean(), self.extracted_grass["b3"].mean(), places=2) self.assertAlmostEqual(df["lsat7_2000_40"].mean(), self.extracted_grass["b4"].mean(), places=2) self.assertAlmostEqual(df["lsat7_2000_50"].mean(), self.extracted_grass["b5"].mean(), places=2) self.assertAlmostEqual(df["lsat7_2000_70"].mean(), self.extracted_grass["b7"].mean(), places=2) def test_extract_lines(self): # extract training data from lines training_py = geopandas.read_file(nc.polygons) training_lines = deepcopy(training_py) training_lines["geometry"] = training_lines.geometry.boundary df = self.stack.extract_vector(gdf=training_lines).dropna() # check shapes of extracted pixels self.assertEqual(df.shape[0], 948) def test_extract_raster(self): # extract training data from labelled pixels with rasterio.open(nc.labelled_pixels) as src: df = self.stack.extract_raster(src) df = df.dropna() self.assertEqual(df.shape[0], self.extracted_grass.shape[0]) self.assertAlmostEqual(df["lsat7_2000_10"].mean(), self.extracted_grass["b1"].mean(), places=3) self.assertAlmostEqual(df["lsat7_2000_20"].mean(), self.extracted_grass["b2"].mean(), places=3) self.assertAlmostEqual(df["lsat7_2000_30"].mean(), self.extracted_grass["b3"].mean(), places=3) self.assertAlmostEqual(df["lsat7_2000_40"].mean(), self.extracted_grass["b4"].mean(), places=3) self.assertAlmostEqual(df["lsat7_2000_50"].mean(), self.extracted_grass["b5"].mean(), places=3) self.assertAlmostEqual(df["lsat7_2000_70"].mean(), self.extracted_grass["b7"].mean(), places=3)