From 78d8c628ece987f89adafe82892800c298d19681 Mon Sep 17 00:00:00 2001 From: Emma Ai Date: Thu, 12 Dec 2024 14:46:36 +1030 Subject: [PATCH] fix nodata ring along the water (#177) Co-authored-by: Emma Ai --- odc/stats/plugins/lc_fc_wo_a0.py | 26 ++++++++++---- tests/test_landcover_plugin_a0.py | 57 +++++++++++++++++++++++-------- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/odc/stats/plugins/lc_fc_wo_a0.py b/odc/stats/plugins/lc_fc_wo_a0.py index a9c37ab..9569a37 100644 --- a/odc/stats/plugins/lc_fc_wo_a0.py +++ b/odc/stats/plugins/lc_fc_wo_a0.py @@ -62,6 +62,15 @@ def native_transform(self, xx): # clear wet pixels not mask against bit 2: low solar angle wet = (xx["water"].data & ~(1 << 2)) == 128 + # get "valid" wo pixels, both dry and wet used in veg_frequency + wet_valid = expr_eval( + "where(a|b, a, _nan)", + {"a": wet, "b": valid}, + name="get_valid_pixels", + dtype="float32", + **{"_nan": np.nan}, + ) + # clear dry pixels clear = xx["water"].data == 0 @@ -81,12 +90,13 @@ def native_transform(self, xx): raw_mask = mask_cleanup( raw_mask, mask_filters=self.cloud_filters.get(key) ) - valid = expr_eval( - "where(b>0, 0, a)", - {"a": valid, "b": raw_mask.data}, + wet_valid = expr_eval( + "where(b>0, _nan, a)", + {"a": wet_valid, "b": raw_mask.data}, name="get_valid_pixels", - dtype="uint8", + dtype="float32", ) + wet_clear = expr_eval( "where(b>0, _nan, a)", {"a": wet_clear, "b": raw_mask.data}, @@ -97,11 +107,13 @@ def native_transform(self, xx): xx = xx.drop_vars(["water"]) - # Pick out the fc pixels that have an unmixing error of less than the threshold + # Pick out the fc pixels that + # have an unmixing error of less than the threshold for dry + # and ignore ue for wet valid = expr_eval( - "where(b<_v, a, 0)", + "where((b>=_v)&(a<=0)|(a!=a), 0, 1)", {"a": valid, "b": xx["ue"].data}, - name="get_low_ue", + name="get_low_ue_wet", dtype="bool", **{"_v": self.ue_threshold}, ) diff --git a/tests/test_landcover_plugin_a0.py b/tests/test_landcover_plugin_a0.py index 0285ec7..458e977 100644 --- a/tests/test_landcover_plugin_a0.py +++ b/tests/test_landcover_plugin_a0.py @@ -329,11 +329,40 @@ def test_native_transform(fc_wo_dataset, bits): assert (a == b).all() result = np.where(out_xx["pv"].data == out_xx["pv"].data) + # fmt: off expected_valid = ( - np.array([0, 0, 2, 3, 3, 3]), - np.array([1, 5, 2, 0, 2, 3]), - np.array([0, 1, 4, 0, 4, 2]), + np.array( + [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, + ] + ), + np.array( + [ + 1, 1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, 1, 1, + 2, 3, 4, 4, 4, 4, 4, 5, 5, 5, 6, 6, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, + 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 0, 0, 0, 1, + 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, + 5, 5, 6, 6, 6, 6, 6, + ] + ), + np.array( + [ + 0, 3, 4, 0, 6, 1, 2, 4, 6, 3, 6, 1, 4, 6, 1, 3, 5, 6, + 5, 4, 0, 1, 2, 4, 5, 0, 2, 6, 3, 6, 0, 3, 4, 5, 6, 0, + 1, 3, 4, 5, 6, 2, 3, 4, 5, 6, 1, 2, 3, 4, 5, 6, 0, 1, + 3, 4, 6, 1, 2, 4, 5, 0, 1, 2, 3, 4, 5, 6, 0, 2, 5, 1, + 3, 4, 5, 6, 0, 2, 3, 4, 1, 2, 5, 6, 0, 1, 3, 5, 0, 1, + 3, 4, 0, 1, 2, 3, 5, + ] + ), ) + # fmt: on for a, b in zip(expected_valid, result): assert (a == b).all() @@ -348,9 +377,9 @@ def test_fusing(fc_wo_dataset): np.array([1, 5, 0, 2, 3]), np.array([0, 1, 0, 4, 2]), ) - pv_valid = np.array([20, 77, 17, 38, 89]) - npv_valid = np.array([85, 47, 63, 64, 19]) - bs_valid = np.array([10, 46, 37, 25, 43]) + pv_valid = np.array([20, 77, 21, 38, 52]) + npv_valid = np.array([85, 47, 73, 64, 10]) + bs_valid = np.array([10, 46, 48, 25, 56]) i = 0 for idx in zip(*valid_index): assert xx.pv.data[idx] == pv_valid[i] @@ -369,7 +398,7 @@ def test_veg_or_not(fc_wo_dataset): np.array([1, 5, 0, 2, 3]), np.array([0, 1, 0, 4, 2]), ) - expected_value = np.array([1, 1, 1, 1, 1]) + expected_value = np.array([1, 1, 1, 1, 0]) i = 0 for idx in zip(*valid_index): assert yy[idx] == expected_value[i] @@ -400,13 +429,13 @@ def test_reduce(fc_wo_dataset): xx = stats_veg.reduce(xx).compute() expected_value = np.array( [ - [2, 255, 255, 255, 255, 255, 255], - [2, 255, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 2, 255, 255], - [255, 255, 2, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255], - [255, 2, 255, 255, 255, 255, 255], - [255, 255, 255, 255, 255, 255, 255], + [2, 255, 2, 2, 2, 2, 2], + [2, 2, 255, 2, 2, 0, 2], + [2, 255, 2, 2, 2, 2, 2], + [255, 2, 2, 2, 3, 2, 2], + [2, 2, 2, 2, 2, 2, 2], + [2, 2, 0, 2, 2, 2, 2], + [2, 2, 2, 2, 2, 2, 2], ], dtype="uint8", )