From d85db6216335f69da1f85768c6d9cad547f77535 Mon Sep 17 00:00:00 2001 From: Paolo Veglio <paolo.veglio@ssec.wisc.edu> Date: Thu, 18 Apr 2024 17:42:32 +0000 Subject: [PATCH] bump version --- mvcm/__init__.py | 3 +- mvcm/main.py | 9 +- pyproject.toml | 1 + tests/test_conf.py | 27 ++++ tests/test_utilities.py | 144 +++++++++++++++++++- thresholds/thresholds.mvcm.snpp.v0.0.1.yaml | 20 +-- 6 files changed, 184 insertions(+), 20 deletions(-) diff --git a/mvcm/__init__.py b/mvcm/__init__.py index 6725e40..cf1769a 100644 --- a/mvcm/__init__.py +++ b/mvcm/__init__.py @@ -1,2 +1,3 @@ """Set up version.""" -__version__ = "0.2.2" + +__version__ = "0.2.3" diff --git a/mvcm/main.py b/mvcm/main.py index bb7d702..197f175 100644 --- a/mvcm/main.py +++ b/mvcm/main.py @@ -269,7 +269,9 @@ def main( np.zeros(viirs_data.M11.shape) * np.nan, dims=viirs_data.M11.dims ) - for scene_name in _scene_list: + scene_types = np.zeros(viirs_data.M11.shape) + for _scene_i, scene_name in enumerate(_scene_list): + scene_types[viirs_data[scene_name].values == 1] = i print(f"Processing {scene_name}") if np.all(viirs_data[scene_name].values == 0): @@ -599,9 +601,10 @@ def main( "M15": {"dims": ("x", "y"), "data": viirs_data.M15.values}, "M15-M12": {"dims": ("x", "y"), "data": viirs_data["M15-M12"].values}, "M15-M16": {"dims": ("x", "y"), "data": viirs_data["M15-M16"].values}, - "Land_Day": {"dims": ("x", "y"), "data": viirs_data.Land_Day.values}, - "Land_Day_Desert": {"dims": ("x", "y"), "data": viirs_data.Land_Day_Desert.values}, + # "Land_Day": {"dims": ("x", "y"), "data": viirs_data.Land_Day.values}, + # "Land_Day_Desert": {"dims": ("x", "y"), "data": viirs_data.Land_Day_Desert.values}, "elevation": {"dims": ("x", "y"), "data": viirs_data.height.values}, + "scene_type": {"dims": ("x", "y"), "data": scene_types}, # 'thr': {'dims': ('x', 'y'), # 'data': thr_temp}, # 'shallow_water_bits': {'dims': ('x', 'y'), diff --git a/pyproject.toml b/pyproject.toml index 20e0cc8..17728ea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,6 +38,7 @@ path = 'mvcm/__init__.py' [tool.hatch.envs.test] dependencies = [ 'pytest', + 'pytest-cov', ] [build-system] diff --git a/tests/test_conf.py b/tests/test_conf.py index 3f6fc54..e34d8bf 100644 --- a/tests/test_conf.py +++ b/tests/test_conf.py @@ -1,37 +1,46 @@ +"""Define tests for confidence calculation.""" + import os import numpy as np import pytest +import ancillary_data as anc import mvcm.conf as conf @pytest.fixture def fixturepath(): + """Define path.""" return os.path.join(os.path.dirname(__file__), "fixtures") @pytest.fixture def rad(): + """Define dummy radiance array.""" return np.arange(260, 282) @pytest.fixture def single_threshold(): + """Define dummy single thresholds.""" return [267, 270, 273, 1] @pytest.fixture def double_threshold(): + """Define dummy double thresholds.""" return [264, 267, 270, 273, 276, 279, 1] @pytest.fixture def reference_data(fixturepath): + """Define reference file name.""" return os.path.join(fixturepath, "ref_conf.npz") def test_single_threshold(rad, single_threshold, reference_data): + """Test single threshold compuputation.""" ref_confidence = np.load(reference_data)["ref_sgl"] ref_confidence_flipped = np.load(reference_data)["ref_sgl_flipped"] @@ -44,6 +53,7 @@ def test_single_threshold(rad, single_threshold, reference_data): def test_double_threshold(rad, double_threshold, reference_data): + """Test double threshold computation.""" ref_confidence = np.load(reference_data)["ref_dbl"] ref_confidence_flipped = np.load(reference_data)["ref_dbl_flipped"] @@ -54,3 +64,20 @@ def test_double_threshold(rad, double_threshold, reference_data): double_threshold[0:-1] = double_threshold[-2::-1] c = conf.conf_test_dble(rad, double_threshold) assert np.all(c == ref_confidence_flipped) + + +def test_c_single_threshold(rad, single_threshold, reference_data): + """Test C version of single threshold computation.""" + ref_confidence = np.load(reference_data)["ref_sgl"] + ref_confidence_flipped = np.load(reference_data)["ref_sgl_flipped"] + + c = anc.py_conf_test( + rad, single_threshold[0], single_threshold[2], single_threshold[3], single_threshold[1] + ) + assert np.all(c == ref_confidence) + + single_threshold[0:-1] = single_threshold[-2::-1] + c = anc.py.conf_test( + rad, single_threshold[0], single_threshold[2], single_threshold[3], single_threshold[1] + ) + assert np.all(c == ref_confidence_flipped) diff --git a/tests/test_utilities.py b/tests/test_utilities.py index dac675f..6b8d6dd 100644 --- a/tests/test_utilities.py +++ b/tests/test_utilities.py @@ -1,4 +1,5 @@ """Test functions for utility_functions module.""" + from typing import Dict import numpy as np @@ -7,8 +8,9 @@ import pytest import mvcm.utility_functions as utils +# FIXTURES @pytest.fixture -def spatial_var_test_arr(): +def test_arr() -> np.ndarray: """Define reference input array for spatial_var() function test.""" arr = np.array( [ @@ -28,6 +30,38 @@ def spatial_var_test_arr(): return arr +@pytest.fixture +def ref_mean() -> np.ndarray: + """Define reference mean array for local_nxn_mean() function test.""" + arr = np.array( + [ + [1.33333333, 2.0, 2.0, 2.0, 1.33333333], + [1.55555556, 2.33333333, 2.33333333, 3.11111111, 2.33333333], + [2.44444444, 3.66666667, 3.66666667, 4.66666667, 3.44444444], + [1.55555556, 2.33333333, 2.33333333, 4.11111111, 3.33333333], + [1.33333333, 2.0, 2.0, 3.0, 2.33333333], + ], + dtype=float, + ) + return arr + + +@pytest.fixture +def ref_std() -> np.ndarray: + """Define reference std array for local_nxn_standard_deviation() function test.""" + arr = np.array( + [ + [2.12132034, 2.29128785, 2.29128785, 2.29128785, 2.12132034], + [2.00693243, 2.0, 2.0, 2.66666667, 2.91547595], + [2.45515331, 2.0, 2.0, 2.34520788, 3.20589734], + [2.00693243, 2.0, 2.0, 3.14024061, 3.60555128], + [2.12132034, 2.29128785, 2.29128785, 3.24037035, 3.35410197], + ], + dtype=float, + ) + return arr + + @pytest.fixture def ref_spatial_var(): """Define reference output array for spatial_var() function test.""" @@ -50,14 +84,112 @@ def ref_spatial_var(): @pytest.fixture -def thresholds(): +def b01() -> np.ndarray: + """Define band 1 for NDVI test.""" + return np.array([0.1, 0.2, 0.3, 0.5]) + + +@pytest.fixture +def b02() -> np.ndarray: + """Define band 2 for NDVI test.""" + return np.array([0.3, 0.3, 0.5, 0.5]) + + +@pytest.fixture +def ref_ndvi() -> np.ndarray: + """Define expected NDVI output.""" + return np.array([0.5, 0.2, 0.25, 0.0]) + + +@pytest.fixture +def thresholds() -> Dict: """Define thresholds for spatial_var() function test.""" return {"thr": 2} -def test_spatial_var( - spatial_var_test_arr: np.ndarray, thresholds: Dict, ref_spatial_var: np.ndarray -) -> None: +@pytest.fixture +def height() -> np.ndarray: + """Define the height array for testing the elevation correction function.""" + return np.array([0, 500, 1000, 1500, 2000, 2500, 3000, 3500, 4000]) + + +@pytest.fixture +def ref_correction() -> np.ndarray: + """Define the expected result of the elevation correction function.""" + return np.array([0, 2.5, 5, 7.5, 10, 12.5, 15, 17.5, 20]) + + +@pytest.fixture +def ref_bits() -> Dict: + """Define dymmy bit values to test the group_counts() function.""" + return { + "01": np.array([1, 0, 0, 1, 1, 1]), + "02": np.array([0, 1, 0, 0, 1, 1]), + "03": np.array([1, 1, 0, 1, 0, 1]), + "04": np.array([0, 0, 1, 1, 1, 1]), + "05": np.array([0, 0, 0, 0, 0, 1]), + "06": np.array([0, 1, 1, 1, 1, 1]), + "07": np.array([1, 0, 1, 0, 1, 1]), + "08": np.array([1, 0, 1, 0, 0, 0]), + "09": np.array([0, 0, 1, 1, 0, 0]), + "10": np.array([1, 1, 0, 1, 1, 0]), + "11": np.array([0, 1, 0, 1, 1, 1]), + "12": np.array([1, 0, 0, 1, 0, 0]), + "13": np.array([1, 0, 1, 1, 0, 1]), + "14": np.array([1, 0, 0, 1, 0, 1]), + "15": np.array([0, 1, 1, 1, 1, 0]), + "16": np.array([0, 0, 1, 0, 1, 0]), + } + + +@pytest.fixture +def ref_group_count() -> np.ndarray: + """Test group_count() function.""" + return np.array([3, 4, 4, 4, 5, 3]) + + +# TESTS +def test_local_nxn_mean(test_arr: np.ndarray, ref_mean: np.ndarray) -> None: + """Test local nxn mean.""" + mean = utils.local_nxn_mean(test_arr[:5, :5], 3, 3) + assert np.allclose(ref_mean, mean) + + +def test_local_nxn_standard_deviation(test_arr: np.ndarray, ref_std: np.ndarray) -> None: + """Test local nxn standard deviation.""" + std = utils.local_nxn_standard_deviation(test_arr[:5, :5], 3, 3) + assert np.allclose(ref_std, std) + + +def test_spatial_var(test_arr: np.ndarray, thresholds: Dict, ref_spatial_var: np.ndarray) -> None: """Test spatial_var function.""" - var = utils.spatial_var(spatial_var_test_arr, thresholds["thr"]) + var = utils.spatial_var(test_arr, thresholds["thr"], vis=True) assert np.allclose(np.floor(var), ref_spatial_var) + + +def test_compute_ndvi(b01: np.ndarray, b02: np.ndarray, ref_ndvi: np.ndarray) -> None: + """Test compute NDVI.""" + ndvi = utils.compute_ndvi(b01, b02) + assert np.allclose(ndvi, ref_ndvi) + pass + + +def test_bt11_elevation_correction(height: np.ndarray, ref_correction: np.ndarray) -> None: + """Test 11um BT elevation correction computation.""" + correction = utils.bt11_elevation_correction(height) + assert np.allclose(correction, ref_correction) + + +def test_group_count(ref_bits: Dict) -> None: + """Test group count.""" + assert np.allclose(utils.group_count(ref_bits), ref_group_count) + + +def test_restoral_flag(bits: np.ndarray) -> None: + """Test computation of restoral flags.""" + pass + + +def test_combine_indices(index1: tuple, index2: tuple, shape: tuple) -> None: + """Test combine indices.""" + pass diff --git a/thresholds/thresholds.mvcm.snpp.v0.0.1.yaml b/thresholds/thresholds.mvcm.snpp.v0.0.1.yaml index 37ec72d..99cc058 100644 --- a/thresholds/thresholds.mvcm.snpp.v0.0.1.yaml +++ b/thresholds/thresholds.mvcm.snpp.v0.0.1.yaml @@ -9,7 +9,6 @@ Land_Day: cmult: 0.3 adj: 1.25 perform: True - dl_ref3_tpw: -10.00 11-4um_Oceanic_Stratus_Test: thr: [-16.0, -14.0, -12.0, 1.0, 1.0] perform: True @@ -19,6 +18,7 @@ Land_Day: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.0, 1.0] + tpw: -10.00 perform: True dlvrat: [1.80, 1.85, 1.90, 1.0, 1.0] # dl11_12lcmult : 0.3 @@ -81,7 +81,6 @@ Land_Day_Coast: cmult: 0.3 adj: 1.25 perform: True - dl_ref3_tpw_t2: -10.00 11-4um_Oceanic_Stratus_Test: thr: [-16.0, -14.0, -12.0, 1.0, 1.0] perform: True @@ -93,6 +92,7 @@ Land_Day_Coast: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.0, 1.0] + tpw: -10.00 perform: True # dl11_12lcmult_t2 : 0.3 # dl11_12hcadj_t2 : 1.25 @@ -125,13 +125,13 @@ Land_Day_Desert: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.0, 1.0] + tpw: -10.00 perform: True GEMI_Test: gemi0: [0.085, 0.095, 0.115, 1.00, 1.0] gemi1: [0.145, 0.170, 0.220, 1.00] gemi2: [0.310, 0.335, 0.360, 1.00] perform: True - lds_ref3_tpw: -10.00 ldsbt1: 320.0 # lds11_12lcmult : 0.3 # lds11_12hcadj : 1.25 @@ -157,8 +157,8 @@ Land_Day_Desert_Coast: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.0, 1.0] + tpw: -10.00 perform: True - lds_ref3_tpw_c: -10.00 ldsbt1_c: 320.0 # lds11_12lcmult_c : 0.3 # lds11_12hcadj_c : 1.25 @@ -271,7 +271,6 @@ Polar_Day_Land: cmult: 0.3 adj: 0.3 perform: True - pdl_ref3_tpw: -10.00 11-4um_Oceanic_Stratus_Test: thr: [-16.0, -14.0, -12.0, 1.0, 1.0] perform: True @@ -282,6 +281,7 @@ Polar_Day_Land: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.0, 1.0] + tpw: -10.00 perform: True Polar_Night_Land: @@ -340,7 +340,6 @@ Polar_Day_Coast: cmult: 0 # I NEED TO WORK ON THIS adj: 0 # I NEED TO WORK ON THIS perform: True - pdl_ref3_tpw_t2: -10.00 11-4um_Oceanic_Stratus_Test: thr: [-16.0, -14.0, -12.0, 1.0, 1.0] perform: True @@ -351,6 +350,7 @@ Polar_Day_Coast: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.0, 1.0] + tpw: -10.00 perform: True Polar_Day_Desert: @@ -371,13 +371,13 @@ Polar_Day_Desert: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.00, 1.0] + tpw: -10.00 perform: True GEMI_Test: gemi0: [0.085, 0.110, 0.135, 1.00, 1.0] gemi1: [0.170, 0.220, 0.270, 1.00] gemi2: [0.310, 0.335, 0.360, 1.00] perform: True - pds_ref3_tpw: -10.00 Polar_Day_Desert_Coast: 11-12um_Cirrus_Test: @@ -397,8 +397,8 @@ Polar_Day_Desert_Coast: perform: True 1.38um_High_Cloud_Test: thr: [0.0375, 0.0250, 0.0125, 1.00, 1.0] + tpw: -10.00 perform: True - pds_ref3_tpw_c: -10.00 Polar_Day_Snow: 11-12um_Cirrus_Test: @@ -406,11 +406,11 @@ Polar_Day_Snow: cmult: 0 # I NEED TO WORK ON THIS adj: 0 # I NEED TO WORK ON THIS perform: True - dps_ref3_tpw: 0.75 dpsbt1: 230.0 Water_Vapor_High_Clouds_Test: [215.0, 220.0, 225.0, 1.0, 1.0] 1.38um_High_Cloud_Test: thr: [0.060, 0.0525, 0.045, 1.0, 1.0] + tpw: 0.75 perform: True 11-4um_BT_Difference_Test_Land: low: [20.0, 18.0, 16.0, 1.0] @@ -568,11 +568,11 @@ Day_Snow: cmult: 0.3 adj: 0 # I NEED TO WORK ON THIS perform: True - ds_ref3_tpw: 0.75 CO2_High_Clouds_Test: [222.0, 224.0, 226.0, 1.0, 1.0] Water_Vapor_High_Clouds_Test: [215.0, 220.0, 225.0, 1.0, 1.0] 1.38um_High_Cloud_Test: thr: [0.060, 0.0525, 0.045, 1.0, 1.0] + tpw: 0.75 perform: True 11-4um_BT_Difference_Test_Land: low: [20.0, 18.0, 16.0, 1.0] -- GitLab