From 52a9fc5d39d8e301fec59f37bc7ed26dc427c0e0 Mon Sep 17 00:00:00 2001 From: tebadi Date: Wed, 23 Oct 2024 23:20:26 +1100 Subject: [PATCH] Added more improvement on level3 and level4 --- .pre-commit-config.yaml | 2 +- .../plugins/l34_utils/l4_bare_gradation.py | 102 ++-- odc/stats/plugins/l34_utils/l4_cultivated.py | 106 ++-- .../plugins/l34_utils/l4_natural_aquatic.py | 455 +++++++++--------- odc/stats/plugins/l34_utils/l4_natural_veg.py | 126 +++-- odc/stats/plugins/l34_utils/l4_surface.py | 35 +- odc/stats/plugins/l34_utils/l4_veg_cover.py | 10 +- odc/stats/plugins/l34_utils/l4_water.py | 54 ++- .../plugins/l34_utils/l4_water_persistence.py | 21 +- odc/stats/plugins/l34_utils/lc_level3.py | 66 ++- odc/stats/plugins/lc_level3.py | 65 --- odc/stats/plugins/lc_level34.py | 125 +++-- tests/test_lc_l4.py | 12 +- tests/test_lc_l4_ctv.py | 76 ++- tests/test_lc_l4_natural_surface.py | 69 +-- tests/test_lc_l4_nav.py | 234 ++++----- tests/test_lc_l4_ntv.py | 89 ++-- tests/test_lc_l4_water.py | 100 ++-- tests/test_lc_level3.py | 32 +- 19 files changed, 830 insertions(+), 949 deletions(-) delete mode 100644 odc/stats/plugins/lc_level3.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7b022429..cbe6fbe5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -40,4 +40,4 @@ repos: "-rn", # Only display messages "-sn", # Don't display the score "--rcfile=pylintrc", # Link to your config file - ] + ] \ No newline at end of file diff --git a/odc/stats/plugins/l34_utils/l4_bare_gradation.py b/odc/stats/plugins/l34_utils/l4_bare_gradation.py index 07b1f19f..81ee9936 100644 --- a/odc/stats/plugins/l34_utils/l4_bare_gradation.py +++ b/odc/stats/plugins/l34_utils/l4_bare_gradation.py @@ -1,53 +1,55 @@ + import xarray as xr from odc.stats._algebra import expr_eval - -def bare_gradation(xx: xr.Dataset, bare_threshold, veg_cover, NODATA): - - # Now add the bare gradation - fcp_nodaata = -999 - bs_mask = expr_eval( - "where(a!=nodata, a, NODATA)", - {"a": xx.bs_pc_50.data}, - name="mark_nodata", - dtype="uint8", - **{"nodata": fcp_nodaata, "NODATA": NODATA}, - ) - - # Map any data > 100 ---> 100 - bs_mask = expr_eval( - "where((a>100)&(a!=nodata), 100, a)", - {"a": bs_mask}, - name="mark_veg", - dtype="uint8", - **{"nodata": NODATA}, - ) - - # 60% <= data --> 15(0) - bs_mask = expr_eval( - "where((a>=m)&(a!=nodata), 150, a)", - {"a": bs_mask}, - name="mark_veg", - dtype="uint8", - **{"m": bare_threshold[1], "nodata": NODATA}, - ) - - # 20% <= data < 60% --> 12(0) - bs_mask = expr_eval( - "where((a>=m)&(a 10(0) - bs_mask = expr_eval( - "where(a 100 ---> 100 + bs_mask = expr_eval( + "where((a>100)&(a!=nodata), 100, a)", + {"a": bs_mask}, + name="mark_veg", + dtype="uint8", + **{"nodata": NODATA}, + ) + + # 60% <= data --> 15(0) + bs_mask = expr_eval( + "where((a>=m)&(a!=nodata), 150, a)", + {"a": bs_mask}, + name="mark_veg", + dtype="uint8", + **{"m": bare_threshold[1], "nodata": NODATA}, + ) + + # 20% <= data < 60% --> 12(0) + bs_mask = expr_eval( + "where((a>=m)&(a 10(0) + bs_mask = expr_eval( + "where(a 0 @@ -77,4 +79,6 @@ def canopyco_veg_con(xx: xr.Dataset, veg_threshold, NODATA, fcp_nodata): **{"m": veg_threshold[4], "n": veg_threshold[5]}, ) + return veg_mask + diff --git a/odc/stats/plugins/l34_utils/l4_water.py b/odc/stats/plugins/l34_utils/l4_water.py index 1965a531..91fed2b8 100644 --- a/odc/stats/plugins/l34_utils/l4_water.py +++ b/odc/stats/plugins/l34_utils/l4_water.py @@ -1,54 +1,72 @@ from odc.stats._algebra import expr_eval +NODATA = 255 -def water_classification(l4, level3, intertidal_mask, water_persistence, NODATA): - - l4 = expr_eval( - "where((c==223)&(a==220)&b, 100, c)", - {"a": level3, "b": intertidal_mask, "c": l4}, - name="mark_water", - dtype="uint8", - ) +def water_classification(l4, level3, intertidal_mask, water_persistence): l4 = expr_eval( "where((c==221)&(a==220)&(b==1), 101, c)", - {"a": level3, "b": water_persistence, "c": l4}, + {"a": level3, + "b": water_persistence, + "c": l4}, name="mark_water", dtype="uint8", ) l4 = expr_eval( "where((c==221)&(a==220)&(b==7), 102, c)", - {"a": level3, "b": water_persistence, "c": l4}, + {"a": level3, + "b": water_persistence, + "c": l4 + }, name="mark_water", dtype="uint8", ) l4 = expr_eval( "where((c==221)&(a==220)&(b==8), 103, c)", - {"a": level3, "b": water_persistence, "c": l4}, + {"a": level3, + "b": water_persistence, + "c": l4}, name="mark_water", dtype="uint8", ) - + l4 = expr_eval( "where((c==221)&(a==220)&(b==9), 104, c)", - {"a": level3, "b": water_persistence, "c": l4}, + {"a": level3, + "b": water_persistence, + "c": l4}, name="mark_water", dtype="uint8", ) - + # L34 water: (water_freq >= 0.2) l4 = expr_eval( "where((a==221)&(b==220)&(c==nodata), 99, a)", - {"a": l4, "b": level3, "c": water_persistence}, + {"a": l4, + "b": level3, + "c": water_persistence}, name="mark_water", dtype="uint8", **{"nodata": NODATA}, ) - + + l4 = expr_eval( + "where((a==220)&(b==1), 100, c)", + {"a": level3, + "b": intertidal_mask, + "c": l4}, + name="mark_water", + dtype="uint8", + ) + l4 = expr_eval( - "where((a==221), 98, a)", {"a": l4}, name="mark_water", dtype="uint8" + "where((a==221), 98, a)", + {"a": l4}, + name="mark_water", + dtype="uint8" ) + - return l4 + return l4 \ No newline at end of file diff --git a/odc/stats/plugins/l34_utils/l4_water_persistence.py b/odc/stats/plugins/l34_utils/l4_water_persistence.py index b2e6dfd3..44542296 100644 --- a/odc/stats/plugins/l34_utils/l4_water_persistence.py +++ b/odc/stats/plugins/l34_utils/l4_water_persistence.py @@ -1,9 +1,10 @@ -import xarray as xr +import xarray as xr + from odc.stats._algebra import expr_eval +NODATA = 255 - -def water_persistence(xx: xr.Dataset, watper_threshold, NODATA): +def water_persistence(xx: xr.Dataset, watper_threshold): # Now add water persistence # water_mask = expr_eval( # "where(a!=a, nodata, a)", @@ -12,7 +13,7 @@ def water_persistence(xx: xr.Dataset, watper_threshold, NODATA): # dtype="uint8", # **{"nodata": NODATA}, # ) - + # 10 <= water_frequency < 1 --> 1(0) water_mask = expr_eval( "where((a>=m)&(a!=nodata), 100, a)", @@ -21,7 +22,7 @@ def water_persistence(xx: xr.Dataset, watper_threshold, NODATA): dtype="uint8", **{"m": watper_threshold[3], "nodata": NODATA}, ) - + # 7 <= water_frequency < 10 --> 7(0) water_mask = expr_eval( "where((a>=m)&(a 8(00) water_mask = expr_eval( "where((a>=m)&(a 9(00) water_mask = expr_eval( "where((a>=m)&(a 0 # water_mask = expr_eval( # "where(a<1, 0, a)", @@ -57,5 +58,5 @@ def water_persistence(xx: xr.Dataset, watper_threshold, NODATA): # dtype="uint8", # **{"m": watper_threshold[0]}, # ) - - return water_mask + + return water_mask \ No newline at end of file diff --git a/odc/stats/plugins/l34_utils/lc_level3.py b/odc/stats/plugins/l34_utils/lc_level3.py index ae8b6ac8..fdf2de4c 100644 --- a/odc/stats/plugins/l34_utils/lc_level3.py +++ b/odc/stats/plugins/l34_utils/lc_level3.py @@ -1,30 +1,54 @@ import xarray as xr +from odc.stats._algebra import expr_eval -def lc_level3(xx: xr.Dataset, NODATA): +NODATA = 255 - l34_dss = xx.classes_l3_l4 - urban_dss = xx.urban_classes - cultivated_dss = xx.cultivated_class - - # Map intertidal areas to water - intertidal_mask = l34_dss == 223 - l34_dss = xr.where(intertidal_mask, 220, l34_dss) +def lc_level3(xx: xr.Dataset): # Cultivated pipeline applies a mask which feeds only terrestrial veg (110) to the model # Just exclude no data (255) and apply the cultivated results - cultivated_mask = cultivated_dss != int(NODATA) - l34_cultivated_masked = xr.where(cultivated_mask, cultivated_dss, l34_dss) - - # Urban is classified on l3/4 surface output (210) - urban_mask = l34_dss == 210 - l34_urban_cultivated_masked = xr.where(urban_mask, urban_dss, l34_cultivated_masked) - - # Replace nan with NODATA - l34_urban_cultivated_masked = xr.where( - l34_urban_cultivated_masked == l34_urban_cultivated_masked, - l34_urban_cultivated_masked, - NODATA, + res = expr_eval( + "where(a Tuple[str, ...]: - _measurements = ["level3_class"] - return _measurements - - def reduce(self, xx: xr.Dataset) -> xr.Dataset: - - # Cultivated pipeline applies a mask which feeds only terrestrial veg (110) to the model - # Just exclude no data (255) and apply the cultivated results - res = expr_eval( - "where(a Tuple[str, ...]: - _measurements = ["level3", "level4"] + _measurements = [ + "level3", + "level4" + ] return _measurements def native_transform(self, xx): @@ -85,24 +76,24 @@ def apply_mapping(data, class_mapping): def define_life_form(self, xx: xr.Dataset): lifeform = xx.woody_cover.data - + # 113 ----> 1 woody # 114 ----> 2 herbaceous lifeform_mask = expr_eval( "where(a==113, 1, a)", {"a": xx.woody_cover.data}, name="mark_lifeform", - dtype="uint8", + dtype="uint8" ) lifeform_mask = expr_eval( "where(a==114, 2, a)", {"a": lifeform_mask}, name="mark_lifeform", - dtype="uint8", + dtype="uint8" ) - + return lifeform_mask - + def define_water_seasonality(self, xx: xr.Dataset): # >= 3 months ----> 1 Semi-permanent or permanent # < 3 months ----> 2 Temporary or seasonal @@ -126,84 +117,76 @@ def define_water_seasonality(self, xx: xr.Dataset): {"a": water_season_mask}, name="mark_water_season", dtype="uint8", - **{ - "watseas_trh": self.water_seasonality_threshold, - "watersea_nodata": water_frequency_nodata, - }, + **{"watseas_trh": self.water_seasonality_threshold, + "watersea_nodata": water_frequency_nodata}, ) - mapping = {100: 1, 200: 2} + mapping = {100:1, 200:2} water_season_mask = self.apply_mapping(water_season_mask, mapping) - + return water_season_mask + def reduce(self, xx: xr.Dataset) -> xr.Dataset: - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) + # Vegetation cover - fc_nodata = -9999 - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, self.veg_threshold, NODATA, fc_nodata - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, self.veg_threshold) # Define mapping from current output to expected a3 output veg_cover = self.apply_mapping(veg_cover, self.veg_mapping) # Define life form lifeform = self.define_life_form(xx) # Apply cultivated Level-4 classes (1-18) - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) + print("***** CULATIVATED: ", np.unique(l4_ctv.compute())) # Apply terrestrial vegetation classes [19-36] - l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg( - l4_ctv, level3, lifeform, veg_cover - ) - + l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) + print("***** CULATIVATED NTV : ", np.unique(l4_ctv_ntv.compute())) + # Bare gradation - bare_gradation = l4_bare_gradation.bare_gradation( - xx, self.bare_threshold, veg_cover, NODATA - ) + bare_gradation = l4_bare_gradation.bare_gradation(xx, self.bare_threshold, veg_cover) # Apply bare gradation expected output classes bare_gradation = self.apply_mapping(bare_gradation, self.bs_mapping) + # Water persistence - water_persistence = l4_water_persistence.water_persistence( - xx, self.watper_threshold, NODATA - ) + water_persistence = l4_water_persistence.water_persistence(xx, self.watper_threshold) # Apply water persistence expcted classes - water_persistence = self.apply_mapping( - water_persistence, self.waterper_wat_mapping - ) - - water_seasonality = self.define_water_seasonality(xx) - - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) - l4_ctv_ntv_nav_surface = l4_surface.lc_l4_surface( - l4_ctv_ntv_nav, level3, bare_gradation - ) + water_persistence = self.apply_mapping(water_persistence, self.waterper_wat_mapping) + + water_seasonality = self.define_water_seasonality(xx) + + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) + print("***** NAV : ", np.unique(l4_ctv_ntv_nav.compute())) + l4_ctv_ntv_nav_surface = l4_surface.lc_l4_surface(l4_ctv_ntv_nav, level3, bare_gradation) + print("***** SURFACE : ", np.unique(l4_ctv_ntv_nav_surface.compute())) # #TODO WATER (99-104) - l4_ctv_ntv_nav_surface_water = l4_water.water_classification( - l4_ctv_ntv_nav_surface, level3, intertidal_mask, water_persistence, NODATA - ) - + level4 = l4_water.water_classification(l4_ctv_ntv_nav_surface, level3, intertidal_mask, water_persistence) + print("***** LEVEL3:", np.unique(level3.compute())) attrs = xx.attrs.copy() attrs["nodata"] = NODATA - l3 = level3.squeeze(dim=["spec"]) - dims = level3.dims - + # l3 = level3.squeeze(dim=["spec"]) + dims = xx.squeeze(dim=["spec"]).dims + attrs = xx.attrs.copy() attrs["nodata"] = int(NODATA) + level3 = level3.astype(np.uint8) + level4 = level4.astype(np.uint8) data_vars = { - "level3": xr.DataArray(level3, dims=xx["pv_pc_50"].dims, attrs=attrs), - "level4": xr.DataArray( - l4_ctv_ntv_nav_surface_water, dims=xx["pv_pc_50"].dims, attrs=attrs + "level3": xr.DataArray( + level3, dims=xx["pv_pc_50"].dims, attrs=attrs ), + "level4": xr.DataArray( + level4, dims=xx["pv_pc_50"].dims, attrs=attrs + ) } - + coords = dict((dim, xx.coords[dim]) for dim in dims) + + print(xr.Dataset(data_vars=data_vars, coords=coords, attrs=xx.attrs)) return xr.Dataset(data_vars=data_vars, coords=coords, attrs=xx.attrs) -register("lc_l3_l4", StatsLccsLevel4) +register("lc_l3_l4", StatsLccsLevel4) \ No newline at end of file diff --git a/tests/test_lc_l4.py b/tests/test_lc_l4.py index 92e57c03..6164d2c4 100644 --- a/tests/test_lc_l4.py +++ b/tests/test_lc_l4.py @@ -1,4 +1,4 @@ -from odc.stats.plugins.lc_level4 import StatsLccsLevel3 +from odc.stats.plugins.lc_level3 import StatsLccsLevel4 import pytest expected_l4_classes = [ @@ -8,6 +8,7 @@ [220, 255, 220], ] +NODATA = 255 @pytest.fixture(scope="module") def image_groups(): @@ -72,9 +73,10 @@ def image_groups(): return xx -def test_l3_classes(image_groups): +def test_l4_classes(image_groups): - lc_level3 = StatsLccsLevel3() - intertidal_mask, level3_classes = lc_level3.reduce(image_groups) + stats_l4 = StatsLccsLevel4() + intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + # intertidal_mask, level3_classes = lc_level3.reduce(image_groups) - assert (level3_classes == expected_l3_classes).all() + assert (level3_classes == expected_l3_classes).all() \ No newline at end of file diff --git a/tests/test_lc_l4_ctv.py b/tests/test_lc_l4_ctv.py index bd21dde9..9495163b 100644 --- a/tests/test_lc_l4_ctv.py +++ b/tests/test_lc_l4_ctv.py @@ -8,12 +8,9 @@ import pandas as pd NODATA = 255 -FC_NODATA = -9999 - -# @pytest.fixture(scope="module") def image_groups(l34, urban, cultivated, woody, pv_pc_50): - + tuples = [ (np.datetime64("2000-01-01T00"), np.datetime64("2000-01-01")), ] @@ -101,7 +98,7 @@ def test_ctv_classes_woody(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -114,21 +111,16 @@ def test_ctv_classes_woody(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) assert (l4_ctv.compute() == expected_cultivated_classes).all() - def test_ctv_classes_herbaceous(): expected_cultivated_classes = [ @@ -185,7 +177,7 @@ def test_ctv_classes_herbaceous(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -198,18 +190,14 @@ def test_ctv_classes_herbaceous(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) assert (l4_ctv.compute() == expected_cultivated_classes).all() @@ -221,7 +209,7 @@ def test_ctv_classes_woody_herbaceous(): [13, 11, 11], [17, 18, 15], ] - + l34 = np.array( [ [ @@ -269,7 +257,7 @@ def test_ctv_classes_woody_herbaceous(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -282,18 +270,14 @@ def test_ctv_classes_woody_herbaceous(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) assert (l4_ctv.compute() == expected_cultivated_classes).all() @@ -305,7 +289,7 @@ def test_ctv_classes_no_vegcover(): [2, 2, 2], [3, 3, 3], ] - + l34 = np.array( [ [ @@ -353,7 +337,7 @@ def test_ctv_classes_no_vegcover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -366,16 +350,12 @@ def test_ctv_classes_no_vegcover(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) - assert (l4_ctv.compute() == expected_cultivated_classes).all() + + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) + assert (l4_ctv.compute() == expected_cultivated_classes).all() \ No newline at end of file diff --git a/tests/test_lc_l4_natural_surface.py b/tests/test_lc_l4_natural_surface.py index b8016840..29fad6cd 100644 --- a/tests/test_lc_l4_natural_surface.py +++ b/tests/test_lc_l4_natural_surface.py @@ -6,26 +6,15 @@ import xarray as xr import dask.array as da from odc.stats.plugins.lc_level34 import StatsLccsLevel4 -from odc.stats.plugins.l34_utils import ( - l4_cultivated, - lc_level3, - l4_veg_cover, - l4_natural_veg, - l4_natural_aquatic, - l4_surface, - l4_bare_gradation, -) +from odc.stats.plugins.l34_utils import l4_cultivated, lc_level3, l4_veg_cover, l4_natural_veg, l4_natural_aquatic, l4_surface, l4_bare_gradation import pytest import pandas as pd NODATA = 255 -FC_NODATA = -999 -WAT_FREQ_NODATA = -999 - def image_groups(l34, urban, woody, bs_pc_50, pv_pc_50, cultivated, water_frequency): - + tuples = [ (np.datetime64("2000-01-01T00"), np.datetime64("2000-01-01")), ] @@ -69,8 +58,8 @@ def test_ns(): [97, 96, 96], [95, 95, 95], [94, 95, 96], - ] - + ] + l34 = np.array( [ [ @@ -94,7 +83,7 @@ def test_ns(): ], dtype="int", ) - + woody = np.array( [ [ @@ -106,7 +95,7 @@ def test_ns(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -122,15 +111,15 @@ def test_ns(): bs_pc_50 = np.array( [ [ - [1, 64, FC_NODATA], + [1, 64, NODATA], [66, 40, 41], [3, 16, 15], - [FC_NODATA, 1, 42], + [NODATA, 1, 42], ] ], dtype="int", ) - # 112 --> natural veg + # 112 --> natural veg cultivated = np.array( [ [ @@ -154,39 +143,27 @@ def test_ns(): ], dtype="int", ) - - xx = image_groups( - l34, urban, woody, bs_pc_50, pv_pc_50, cultivated, water_frequency - ) - + + xx = image_groups(l34, urban, woody, bs_pc_50, pv_pc_50, cultivated, water_frequency) + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) - - # Bare gradation - bare_gradation = l4_bare_gradation.bare_gradation( - xx, stats_l4.bare_threshold, veg_cover, NODATA - ) + # Bare gradation + bare_gradation = l4_bare_gradation.bare_gradation(xx, stats_l4.bare_threshold, veg_cover) # Apply bare gradation expected output classes bare_gradation = stats_l4.apply_mapping(bare_gradation, stats_l4.bs_mapping) - - l4_ctv_ntv_nav_surface = l4_surface.lc_l4_surface( - l4_ctv_ntv_nav, level3, bare_gradation - ) - + + l4_ctv_ntv_nav_surface = l4_surface.lc_l4_surface(l4_ctv_ntv_nav, level3, bare_gradation) + assert (l4_ctv_ntv_nav_surface.compute() == expected_l4_srf_classes).all() diff --git a/tests/test_lc_l4_nav.py b/tests/test_lc_l4_nav.py index b37b7315..c4e122f2 100644 --- a/tests/test_lc_l4_nav.py +++ b/tests/test_lc_l4_nav.py @@ -6,25 +6,15 @@ import xarray as xr import dask.array as da from odc.stats.plugins.lc_level34 import StatsLccsLevel4 -from odc.stats.plugins.l34_utils import ( - l4_cultivated, - lc_level3, - l4_veg_cover, - l4_natural_veg, - l4_water_persistence, - l4_natural_aquatic, -) +from odc.stats.plugins.l34_utils import l4_cultivated, lc_level3, l4_veg_cover, l4_natural_veg, l4_water_persistence, l4_natural_aquatic import pytest import pandas as pd NODATA = 255 -FC_NODATA = -9999 -WAT_FREQ_NODATA = -9999 - def image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency): - + tuples = [ (np.datetime64("2000-01-01T00"), np.datetime64("2000-01-01")), ] @@ -60,7 +50,12 @@ def image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency): def test_ntv_classes_woody_herbaceous(): - expected_l4_ntv_classes = [[56, 56, 56], [56, 56, 55], [57, 57, 57], [57, 57, 55]] + expected_l4_ntv_classes = [ + [56, 56, 56], + [56, 56, 55], + [57, 57, 57], + [57, 57, 55] + ] l34 = np.array( [ @@ -109,7 +104,7 @@ def test_ntv_classes_woody_herbaceous(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -121,7 +116,7 @@ def test_ntv_classes_woody_herbaceous(): ], dtype="int", ) - + water_frequency = np.array( [ [ @@ -133,27 +128,21 @@ def test_ntv_classes_woody_herbaceous(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() @@ -213,7 +202,7 @@ def test_ntv_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -228,7 +217,7 @@ def test_ntv_veg_cover(): water_frequency = np.array( [ [ - [-9999, -9999, -9999], + [-9999, -9999,- 9999], [-9999, -9999, -9999], [-9999, -9999, -9999], [-9999, -9999, -9999], @@ -236,30 +225,23 @@ def test_ntv_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() - def test_ntv_woody_veg_cover(): expected_l4_ntv_classes = [ [75, 66, 63], @@ -315,7 +297,7 @@ def test_ntv_woody_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -330,7 +312,7 @@ def test_ntv_woody_veg_cover(): water_frequency = np.array( [ [ - [-9999, -9999, -9999], + [-9999, -9999,- 9999], [-9999, -9999, -9999], [-9999, -9999, -9999], [-9999, -9999, -9999], @@ -338,27 +320,21 @@ def test_ntv_woody_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() @@ -417,7 +393,7 @@ def test_ntv_woody_seasonal_water_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -440,31 +416,24 @@ def test_ntv_woody_seasonal_water_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() - def test_ntv_woody_permanent_water_veg_cover(): expected_l4_ntv_classes = [ [76, 67, 64], @@ -520,7 +489,7 @@ def test_ntv_woody_permanent_water_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -543,32 +512,30 @@ def test_ntv_woody_permanent_water_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() - def test_ntv_herbaceous_veg_cover(): - expected_l4_ntv_classes = [[90, 81, 78], [78, 81, 81], [90, 84, 84], [87, 90, 81]] + expected_l4_ntv_classes = [ + [90, 81, 78], + [78, 81, 81], + [90, 84, 84], + [87, 90, 81] + ] l34 = np.array( [ @@ -617,7 +584,7 @@ def test_ntv_herbaceous_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -632,7 +599,7 @@ def test_ntv_herbaceous_veg_cover(): water_frequency = np.array( [ [ - [-9999, -9999, -9999], + [-9999, -9999,- 9999], [-9999, -9999, -9999], [-9999, -9999, -9999], [-9999, -9999, -9999], @@ -640,27 +607,21 @@ def test_ntv_herbaceous_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() @@ -719,7 +680,7 @@ def test_ntv_herbaceous_seasonal_water_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -742,31 +703,24 @@ def test_ntv_herbaceous_seasonal_water_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() - def test_ntv_herbaceous_permanent_water_veg_cover(): expected_l4_ntv_classes = [ [91, 82, 79], @@ -822,7 +776,7 @@ def test_ntv_herbaceous_permanent_water_veg_cover(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -845,25 +799,19 @@ def test_ntv_herbaceous_permanent_water_veg_cover(): ], dtype="int", ) - + xx = image_groups(l34, urban, cultivated, woody, pv_pc_50, water_frequency) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) # Apply cultivated to match the code in Level4 processing - l4_ctv = l4_cultivated.lc_l4_cultivated( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ctv = l4_cultivated.lc_l4_cultivated(xx.classes_l3_l4, level3, lifeform, veg_cover) l4_ctv_ntv = l4_natural_veg.lc_l4_natural_veg(l4_ctv, level3, lifeform, veg_cover) - - water_seasonality = stats_l4.define_water_seasonality(xx) - l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg( - l4_ctv_ntv, lifeform, veg_cover, water_seasonality - ) - assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() + + water_seasonality = stats_l4.define_water_seasonality(xx) + l4_ctv_ntv_nav = l4_natural_aquatic.natural_auquatic_veg(l4_ctv_ntv, lifeform, veg_cover, water_seasonality) + assert (l4_ctv_ntv_nav.compute() == expected_l4_ntv_classes).all() \ No newline at end of file diff --git a/tests/test_lc_l4_ntv.py b/tests/test_lc_l4_ntv.py index 4059e679..c404f672 100644 --- a/tests/test_lc_l4_ntv.py +++ b/tests/test_lc_l4_ntv.py @@ -6,23 +6,16 @@ import xarray as xr import dask.array as da from odc.stats.plugins.lc_level34 import StatsLccsLevel4 -from odc.stats.plugins.l34_utils import ( - l4_cultivated, - lc_level3, - l4_veg_cover, - l4_natural_veg, -) +from odc.stats.plugins.l34_utils import l4_cultivated, lc_level3, l4_veg_cover, l4_natural_veg import pytest import pandas as pd NODATA = 255 -FC_NODATA = -9999 - # @pytest.fixture(scope="module") def image_groups(l34, urban, cultivated, woody, pv_pc_50): - + tuples = [ (np.datetime64("2000-01-01T00"), np.datetime64("2000-01-01")), ] @@ -55,12 +48,12 @@ def image_groups(l34, urban, cultivated, woody, pv_pc_50): def test_ntv_classes_herbaceous(): - + expected_natural_terrestrial_veg_classes = [ [36, 33, 32], [110, 33, 33], [36, 34, 34], - [35, 36, 33], + [35, 36, 33] ] l34 = np.array( @@ -110,7 +103,7 @@ def test_ntv_classes_herbaceous(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -123,28 +116,24 @@ def test_ntv_classes_herbaceous(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - l4_ntv = l4_natural_veg.lc_l4_natural_veg( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ntv = l4_natural_veg.lc_l4_natural_veg(xx.classes_l3_l4, level3, lifeform, veg_cover) assert (l4_ntv.compute() == expected_natural_terrestrial_veg_classes).all() def test_ntv_classes_woody(): - + expected_natural_terrestrial_veg_classes = [ - [31, 28, 27], + [31, 28, 27], [110, 28, 28], [31, 29, 29], - [30, 26, 28], + [30, 26, 28] ] l34 = np.array( @@ -194,7 +183,7 @@ def test_ntv_classes_woody(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -207,28 +196,23 @@ def test_ntv_classes_woody(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - l4_ntv = l4_natural_veg.lc_l4_natural_veg( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ntv = l4_natural_veg.lc_l4_natural_veg(xx.classes_l3_l4, level3, lifeform, veg_cover) assert (l4_ntv.compute() == expected_natural_terrestrial_veg_classes).all() - def test_ntv_classes_no_veg(): - + expected_natural_terrestrial_veg_classes = [ [20, 20, 20], [110, 21, 21], [20, 20, 20], - [21, 21, 21], + [21, 21, 21] ] l34 = np.array( @@ -278,7 +262,7 @@ def test_ntv_classes_no_veg(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -291,28 +275,23 @@ def test_ntv_classes_no_veg(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - l4_ntv = l4_natural_veg.lc_l4_natural_veg( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) + l4_ntv = l4_natural_veg.lc_l4_natural_veg(xx.classes_l3_l4, level3, lifeform, veg_cover) assert (l4_ntv.compute() == expected_natural_terrestrial_veg_classes).all() - def test_ntv_classes_no_lifeform(): - + expected_natural_terrestrial_veg_classes = [ [26, 23, 22], [22, 23, 23], [26, 24, 24], - [25, 26, 23], + [25, 26, 23] ] l34 = np.array( @@ -362,7 +341,7 @@ def test_ntv_classes_no_lifeform(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -375,16 +354,12 @@ def test_ntv_classes_no_lifeform(): dtype="int", ) xx = image_groups(l34, urban, cultivated, woody, pv_pc_50) - + stats_l4 = StatsLccsLevel4() - intertidal_mask, level3 = lc_level3.lc_level3(xx, NODATA) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - l4_ntv = l4_natural_veg.lc_l4_natural_veg( - xx.classes_l3_l4, level3, lifeform, veg_cover - ) - assert (l4_ntv.compute() == expected_natural_terrestrial_veg_classes).all() + l4_ntv = l4_natural_veg.lc_l4_natural_veg(xx.classes_l3_l4, level3, lifeform, veg_cover) + assert (l4_ntv.compute() == expected_natural_terrestrial_veg_classes).all() \ No newline at end of file diff --git a/tests/test_lc_l4_water.py b/tests/test_lc_l4_water.py index b0448bc6..3fb02615 100644 --- a/tests/test_lc_l4_water.py +++ b/tests/test_lc_l4_water.py @@ -6,29 +6,16 @@ import xarray as xr import dask.array as da from odc.stats.plugins.lc_level34 import StatsLccsLevel4 -from odc.stats.plugins.lc_level3 import StatsLccsLevel3 -from odc.stats.plugins.l34_utils import ( - l4_cultivated, - lc_level3, - l4_veg_cover, - l4_natural_veg, - l4_natural_aquatic, - l4_bare_gradation, - l4_water_persistence, - l4_surface, - l4_water, -) +from odc.stats.plugins.l34_utils import l4_cultivated, lc_level3, l4_veg_cover, l4_natural_veg, l4_natural_aquatic, l4_bare_gradation, l4_water_persistence, l4_surface, l4_water import pytest import pandas as pd NODATA = 255 -FC_NODATA = -999 - # @pytest.fixture(scope="module") def image_groups(l34, urban, cultivated, woody, bs_pc_50, pv_pc_50, water_frequency): - + tuples = [ (np.datetime64("2000-01-01T00"), np.datetime64("2000-01-01")), ] @@ -67,12 +54,15 @@ def image_groups(l34, urban, cultivated, woody, bs_pc_50, pv_pc_50, water_freque def test_water_classes(): - + # [[[ 98 98 98] + # [103 98 98] + # [ 98 98 98] + # [ 98 98 98]]] expected_water_classes = [ [104, 104, 104], [103, 103, 103], [102, 102, 101], - [101, 101, 101], + [101, 101, 101] ] l34 = np.array( @@ -122,7 +112,7 @@ def test_water_classes(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -137,10 +127,10 @@ def test_water_classes(): bs_pc_50 = np.array( [ [ - [1, 64, FC_NODATA], + [1, 64, NODATA], [66, 40, 41], [3, 16, 15], - [FC_NODATA, 1, 42], + [NODATA, 1, 42], ] ], dtype="int", @@ -156,42 +146,30 @@ def test_water_classes(): ], dtype="int", ) - xx = image_groups( - l34, urban, cultivated, woody, bs_pc_50, pv_pc_50, water_frequency - ) - + xx = image_groups(l34, urban, cultivated, woody, bs_pc_50, pv_pc_50, water_frequency) + stats_l4 = StatsLccsLevel4() - stats_l3 = StatsLccsLevel3() - intertidal_mask, level3 = stats_l3.reduce(xx) + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - + # Water persistence - water_persistence = l4_water_persistence.water_persistence( - xx, stats_l4.watper_threshold, NODATA - ) + water_persistence = l4_water_persistence.water_persistence(xx, stats_l4.watper_threshold) # Apply water persistence expcted classes - water_persistence = stats_l4.apply_mapping( - water_persistence, stats_l4.waterper_wat_mapping - ) - l4_water_classes = l4_water.water_classification( - xx.classes_l3_l4, level3, intertidal_mask, water_persistence, NODATA - ) - + water_persistence = stats_l4.apply_mapping(water_persistence, stats_l4.waterper_wat_mapping) + l4_water_classes = l4_water.water_classification(xx.classes_l3_l4, level3, intertidal_mask, water_persistence) + assert (l4_water_classes.compute() == expected_water_classes).all() - def test_water_intertidal(): - + expected_water_classes = [ [104, 104, 104], [103, 103, 103], [102, 102, 101], - [101, 99, 99], + [101, 99, 99] ] l34 = np.array( @@ -241,7 +219,7 @@ def test_water_intertidal(): ], dtype="int", ) - + pv_pc_50 = np.array( [ [ @@ -256,10 +234,10 @@ def test_water_intertidal(): bs_pc_50 = np.array( [ [ - [1, 64, FC_NODATA], + [1, 64, NODATA], [66, 40, 41], [3, 16, 15], - [FC_NODATA, 1, 42], + [NODATA, 1, 42], ] ], dtype="int", @@ -275,30 +253,18 @@ def test_water_intertidal(): ], dtype="int", ) - xx = image_groups( - l34, urban, cultivated, woody, bs_pc_50, pv_pc_50, water_frequency - ) - + xx = image_groups(l34, urban, cultivated, woody, bs_pc_50, pv_pc_50, water_frequency) + stats_l4 = StatsLccsLevel4() - stats_l3 = StatsLccsLevel3() - intertidal_mask, level3 = stats_l3.reduce(xx) - + intertidal_mask, level3 = lc_level3.lc_level3(xx) lifeform = stats_l4.define_life_form(xx) - veg_cover = l4_veg_cover.canopyco_veg_con( - xx, stats_l4.veg_threshold, NODATA, FC_NODATA - ) + veg_cover = l4_veg_cover.canopyco_veg_con(xx, stats_l4.veg_threshold) veg_cover = stats_l4.apply_mapping(veg_cover, stats_l4.veg_mapping) - + # Water persistence - water_persistence = l4_water_persistence.water_persistence( - xx, stats_l4.watper_threshold, NODATA - ) + water_persistence = l4_water_persistence.water_persistence(xx, stats_l4.watper_threshold) # Apply water persistence expcted classes - water_persistence = stats_l4.apply_mapping( - water_persistence, stats_l4.waterper_wat_mapping - ) - l4_water_classes = l4_water.water_classification( - xx.classes_l3_l4, level3, intertidal_mask, water_persistence, NODATA - ) + water_persistence = stats_l4.apply_mapping(water_persistence, stats_l4.waterper_wat_mapping) + l4_water_classes = l4_water.water_classification(xx.classes_l3_l4, level3, intertidal_mask, water_persistence) - assert (l4_water_classes.compute() == expected_water_classes).all() + assert (l4_water_classes.compute() == expected_water_classes).all() \ No newline at end of file diff --git a/tests/test_lc_level3.py b/tests/test_lc_level3.py index 8ec8a995..a13e892a 100644 --- a/tests/test_lc_level3.py +++ b/tests/test_lc_level3.py @@ -1,11 +1,12 @@ import numpy as np import pandas as pd import xarray as xr -import dask.array as da -from odc.stats.plugins.lc_level3 import StatsLccsLevel3 +from odc.stats.plugins.l34_utils import lc_level3 import pytest +NODATA = 255 + expected_l3_classes = [ [111, 112, 215], [124, 112, 215], @@ -13,7 +14,6 @@ [220, 255, 220], ] - @pytest.fixture(scope="module") def image_groups(): l34 = np.array( @@ -25,7 +25,7 @@ def image_groups(): [223, 255, 223], ] ], - dtype="uint8", + dtype="int", ) urban = np.array( @@ -37,7 +37,7 @@ def image_groups(): [216, 216, 216], ] ], - dtype="uint8", + dtype="int", ) cultivated = np.array( @@ -49,7 +49,7 @@ def image_groups(): [255, 255, 255], ] ], - dtype="uint8", + dtype="int", ) tuples = [ @@ -64,19 +64,13 @@ def image_groups(): data_vars = { "classes_l3_l4": xr.DataArray( - da.from_array(l34, chunks=(1, -1, -1)), - dims=("spec", "y", "x"), - attrs={"nodata": 255}, + l34, dims=("spec", "y", "x"), attrs={"nodata": 255} ), "urban_classes": xr.DataArray( - da.from_array(urban, chunks=(1, -1, -1)), - dims=("spec", "y", "x"), - attrs={"nodata": 255}, + urban, dims=("spec", "y", "x"), attrs={"nodata": 255} ), "cultivated_class": xr.DataArray( - da.from_array(cultivated, chunks=(1, -1, -1)), - dims=("spec", "y", "x"), - attrs={"nodata": 255}, + cultivated, dims=("spec", "y", "x"), attrs={"nodata": 255} ), } xx = xr.Dataset(data_vars=data_vars, coords=coords) @@ -85,7 +79,7 @@ def image_groups(): def test_l3_classes(image_groups): - lc_level3 = StatsLccsLevel3() - intertidal_mask, level3_classes = lc_level3.reduce(image_groups) - - assert (level3_classes == expected_l3_classes).all() + intertidal_mask, level3_classes = lc_level3.lc_level3(image_groups) + print(level3_classes.compute()) + print("*********") + assert (level3_classes.compute() == expected_l3_classes).all()