From c2c16d330aa6e1229cc9d55453b89feee8c5af34 Mon Sep 17 00:00:00 2001
From: Paolo Veglio <paolo.veglio@ssec.wisc.edu>
Date: Mon, 18 Jul 2022 21:51:21 +0000
Subject: [PATCH] changes to main code to simulate the group testing found in
 MVCM

---
 main.py            | 106 ++++++++++------
 ocean_day_tests.py | 305 +++++++++++++++++++++++++++++++++++++++++++++
 read_data.py       |   2 +-
 tests.py           |   2 +
 utils.py           |   2 +-
 5 files changed, 378 insertions(+), 39 deletions(-)
 create mode 100644 ocean_day_tests.py

diff --git a/main.py b/main.py
index 6c7c0ed..0541ac5 100644
--- a/main.py
+++ b/main.py
@@ -2,29 +2,34 @@ import ruamel_yaml as yml
 import numpy as np
 # import xarray as xr
 
+from glob import glob
+
 import read_data as rd
-import tests
+import scene as scn
+# import tests
+import ocean_day_tests as odt
 
 # #################################################################### #
 # TEST CASE
 # data:
 _datapath = '/ships19/hercules/pveglio/mvcm_viirs_hires'
-_fname_mod02 = 'VNP02MOD.A2022173.0336.001.2022173154147.uwssec.nc'
-_fname_mod03 = 'VNP03MOD.A2022173.0336.001.2022173155356.uwssec.nc'
-_fname_img02 = 'VNP02IMG.A2022173.0336.001.2022173154147.uwssec.nc'
-_fname_img03 = 'VNP03IMG.A2022173.0336.001.2022173155356.uwssec.nc'
+_fname_mod02 = glob(f'{_datapath}/VNP02MOD.A2022173.1454.001.*.uwssec.nc')[0]
+_fname_mod03 = glob(f'{_datapath}/VNP03MOD.A2022173.1454.001.*.uwssec.nc')[0]
+_fname_img02 = glob(f'{_datapath}/VNP02IMG.A2022173.1454.001.*.uwssec.nc')[0]
+_fname_img03 = glob(f'{_datapath}/VNP03IMG.A2022173.1454.001.*.uwssec.nc')[0]
 
 # thresholds:
 _threshold_file = '/home/pveglio/mvcm_leo/thresholds/new_thresholds.mvcm.snpp.v1.0.0.yaml'
 
 # ancillary files:
-_geos_atm_1 = 'GEOS.fpit.asm.inst3_2d_asm_Nx.GEOS5124.20220622_0300.V01.nc4'
-_geos_atm_2 = 'GEOS.fpit.asm.inst3_2d_asm_Nx.GEOS5124.20220622_0600.V01.nc4'
-_geos_land = 'GEOS.fpit.asm.tavg1_2d_lnd_Nx.GEOS5124.20220622_0330.V01.nc4'
-_geos_ocean = 'GEOS.fpit.asm.tavg1_2d_ocn_Nx.GEOS5124.20220622_0330.V01.nc4'
+_geos_atm_1 = 'GEOS.fpit.asm.inst3_2d_asm_Nx.GEOS5124.20220622_1200.V01.nc4'
+_geos_atm_2 = 'GEOS.fpit.asm.inst3_2d_asm_Nx.GEOS5124.20220622_1500.V01.nc4'
+_geos_land = 'GEOS.fpit.asm.tavg1_2d_lnd_Nx.GEOS5124.20220622_1430.V01.nc4'
+_geos_ocean = 'GEOS.fpit.asm.tavg1_2d_ocn_Nx.GEOS5124.20220622_1430.V01.nc4'
 _geos_constants = 'GEOS.fp.asm.const_2d_asm_Nx.00000000_0000.V01.nc4'
 _ndvi_file = 'NDVI.FM.c004.v2.0.WS.00-04.177.hdf'
 _sst_file = 'oisst.20220622'
+_eco_file = 'goge1_2_img.v1'
 
 # #################################################################### #
 
@@ -39,17 +44,17 @@ def main(*, data_path=_datapath, mod02=_fname_mod02, mod03=_fname_mod03,
     # fname_geo = 'VNP03MOD.A2014213.1548.001.2017301015705.uwssec.nc'
     # thresh_file = '/home/pveglio/mvcm_leo/thresholds/new_thresholds.mvcm.snpp.v1.0.0.yaml'
 
-    ancillary_file_names = {'GEOS_atm_1': f'{data_path}/ancillary/{geos_atm_1}',
-                            'GEOS_atm_2': f'{data_path}/ancillary/{geos_atm_2}',
-                            'GEOS_land': f'{data_path}/ancillary/{geos_land}',
-                            'GEOS_ocean': f'{data_path}/ancillary/{geos_ocean}',
-                            'GEOS_constants': f'{data_path}/ancillary/{geos_constants}',
-                            'NDVI': f'{data_path}/ancillary/{ndvi_file}',
-                            'SST': f'{data_path}/ancillary/{sst_file}',
+    ancillary_file_names = {'GEOS_atm_1': f'{geos_atm_1}',
+                            'GEOS_atm_2': f'{geos_atm_2}',
+                            'GEOS_land': f'{geos_land}',
+                            'GEOS_ocean': f'{geos_ocean}',
+                            'GEOS_constants': f'{geos_constants}',
+                            'NDVI': f'{ndvi_file}',
+                            'SST': f'{sst_file}',
                             'ANC_DIR': f'{data_path}/ancillary'
                             }
 
-    viirs_data = rd.read_data('viirs', f'{data_path}/{mod02}', f'{data_path}/{mod03}')
+    viirs_data = rd.read_data('viirs', f'{mod02}', f'{mod03}')
 
     viirs_data = rd.read_ancillary_data(ancillary_file_names, viirs_data)
 
@@ -57,26 +62,53 @@ def main(*, data_path=_datapath, mod02=_fname_mod02, mod03=_fname_mod03,
         text = f.read()
     thresholds = yml.safe_load(text)
 
-    confidence = np.zeros((5, viirs_data['M01'].shape[0], viirs_data['M01'].shape[1]))
-
-    confidence[0, :, :] = tests.test_11um(viirs_data.M15.values, thresholds['Daytime_Ocean'])
-    confidence[1, :, :] = tests.test_11_4diff(viirs_data.M15.values, viirs_data.M13.values,
-                                              thresholds['Daytime_Ocean'], viirs_data,
-                                              thresholds['Sun_Glint']['bounds'][3])
-
-    confidence[2, :, :] = tests.nir_refl_test(viirs_data.M07.values, thresholds['Daytime_Ocean'],
-                                              thresholds['Sun_Glint'], viirs_data)
-
-    # Note that here I'm using M05/M07 but the corresponding hi-res channels are I1/I2
-    # IMPORTANT: conf_test_dble() needs to be verified. I don't think it's working as intended at the moment
-    confidence[3, :, :] = tests.vis_nir_ratio_test(viirs_data.M05.values, viirs_data.M07.values,
-                                                   thresholds['Daytime_Ocean'], thresholds['Sun_Glint'])
-
-    # This test needs to be verified, for the granule I'm running everything is zero
-    confidence[4, :, :] = tests.test_11um_var(viirs_data.M15.values, thresholds['Nighttime_Ocean'],
-                                              thresholds['Daytime_Ocean_Spatial_Variability'])
-
-    return confidence
+    sunglint_angle = thresholds['Sun_Glint']['bounds'][3]
+    scene_flags = scn.find_scene(viirs_data, sunglint_angle)
+
+    cmin1 = np.ones(viirs_data.M01.shape)
+    cmin2 = np.ones(viirs_data.M01.shape)
+    cmin3 = np.ones(viirs_data.M01.shape)
+    cmin4 = np.ones(viirs_data.M01.shape)
+
+    # confidence = np.zeros((8, viirs_data['M01'].shape[0], viirs_data['M01'].shape[1]))
+    cmin1 = odt.simple_test(viirs_data.M15.values, thresholds['Daytime_Ocean']['bt11'], cmin1)
+    cmin1 = odt.sst_test(viirs_data.M15.values, viirs_data.M16.values,
+                         viirs_data.sensor_zenith.values, viirs_data.geos_sfct.values,
+                         thresholds['Daytime_Ocean']['sst'], cmin1)
+    cmin2 = odt.simple_test(viirs_data.M14.values-viirs_data.M15.values,
+                            thresholds['Daytime_Ocean']['diff_11_86um'], cmin2)
+    # PLACEHOLDER FOR 11-12 MICRON BTD TEST UNTIL I INCLUDE THE CITHR() FUNCTION FROM C IN CYTHON
+    cmin2 = odt.test_11_12_diff(viirs_data.M15.values, viirs_data.M16.values,
+                                thresholds['Daytime_Ocean']['diff11_12um'], cmin2)
+    cmin2 = odt.test_11_4_diff(viirs_data.M15.values, viirs_data.M12.values,
+                               thresholds['Daytime_Ocean']['test11_4lo'], cmin2)
+    cmin3 = odt.nir_refl_test(viirs_data.M07.values, thresholds['Daytime_Ocean'],
+                              thresholds['Sun_Glint'], viirs_data, cmin3)
+    cmin3 = odt.vis_nir_ratio_test(viirs_data.M05.values, viirs_data.M07.values,
+                                   thresholds['Daytime_Ocean'], thresholds['Sun_Glint'], cmin3)
+    cmin3 = odt.nir_refl_test(viirs_data.M10.values, thresholds['Daytime_Ocean'],
+                              thresholds['Sun_Glint'], viirs_data, cmin3)
+#
+#    confidence[0, :, :] = tests.test_11um(viirs_data.M15.values, thresholds['Daytime_Ocean'])
+#    confidence[1, :, :] = tests.test_11_4diff(viirs_data.M15.values, viirs_data.M13.values,
+#                                              thresholds['Daytime_Ocean'], viirs_data,
+#                                              thresholds['Sun_Glint']['bounds'][3])
+#
+#    confidence[2, :, :] = tests.nir_refl_test(viirs_data.M07.values, thresholds['Daytime_Ocean'],
+#                                              thresholds['Sun_Glint'], viirs_data)
+#
+#    # Note that here I'm using M05/M07 but the corresponding hi-res channels are I1/I2
+#    # IMPORTANT: conf_test_dble() needs to be verified. I don't think it's working as intended at the moment
+#    confidence[3, :, :] = tests.vis_nir_ratio_test(viirs_data.M05.values, viirs_data.M07.values,
+#                                                   thresholds['Daytime_Ocean'], thresholds['Sun_Glint'])
+#
+#    # This test needs to be verified, for the granule I'm running everything is zero
+#    confidence[4, :, :] = tests.test_11um_var(viirs_data.M15.values, thresholds['Nighttime_Ocean'],
+#                                              thresholds['Daytime_Ocean_Spatial_Variability'])
+
+    confidence = cmin1 * cmin2 * cmin3 * cmin4
+
+    return cmin1, cmin2, cmin3
 
 
 def test_main():
diff --git a/ocean_day_tests.py b/ocean_day_tests.py
new file mode 100644
index 0000000..e0f1db5
--- /dev/null
+++ b/ocean_day_tests.py
@@ -0,0 +1,305 @@
+import numpy as np
+
+from numpy.lib.stride_tricks import sliding_window_view
+
+import utils
+import conf
+
+
+# ############## GROUP 1 TESTS ############## #
+
+# 11 micron brightness temperature threshold test
+def simple_test(rad, threshold, cmin):
+
+    radshape = rad.shape
+    rad = rad.reshape(np.prod(radshape))
+
+    thr = np.array(threshold)
+    confidence = np.ones(rad.shape)
+
+    if thr[4] == 1:
+        print("simple test running")
+        # the C code has the line below that I don't quite understand the purpose of.
+        # It seems to be setting the bit to 0 if the BT value is greater than the midpoint
+        #
+        # if (m31 >= dobt11[1]) (void) set_bit(13, pxout.testbits);
+
+        # confidence = utils.conf_test(rad, thr)
+        confidence = conf.conf_test(rad, thr)
+
+    return np.minimum(cmin, confidence.reshape(radshape))
+
+
+def sst_test(rad1, rad2, vza, surf_temp, threshold, cmin):
+
+    a1 = 1.8860
+    a2 = 0.9380
+    a3 = 0.1280
+    a4 = 1.0940
+
+    radshape = rad1.shape
+    b31 = rad1.reshape(np.prod(radshape)) - 273.16
+    b32 = rad2.reshape(np.prod(radshape)) - 273.16
+
+    thr = np.array(threshold)
+    confidence = np.ones(b31.shape)
+
+    rad_diff = b31 - b32
+    sstc = surf_temp.reshape(np.prod(radshape)) - 273.16
+    mu = np.cos(vza.reshape(np.prod(radshape)) * np.pi/180.0)
+
+    modsst = 273.16 + a1 + a2*b31 + a3*rad_diff*sstc + a4*rad_diff*((1/mu)-1)
+    sfcdif = surf_temp.reshape(np.prod(radshape)) - modsst
+
+    if thr[4] == 1:
+        print('SST test running')
+        confidence = conf.conf_test(sfcdif, thr)
+
+    return np.minimum(cmin, confidence.reshape(radshape))
+
+
+def test_11_12_diff(rad1, rad2, threshold, cmin):
+    radshape = rad1.shape
+    b31 = rad1.reshape(np.prod(radshape))
+    b32 = rad2.reshape(np.prod(radshape))
+    thr = np.array(threshold)
+
+    confidence = np.ones(b31.shape)
+    rad_diff = b31 - b32
+
+    if thr[1] == 1:
+        print('11-12um diff test running')
+
+    return np.minimum(cmin, confidence.reshape(radshape))
+
+
+def test_11_4_diff(rad1, rad2, threshold, cmin):
+    radshape = rad1.shape
+    b31 = rad1.reshape(np.prod(radshape))
+    b20 = rad2.reshape(np.prod(radshape))
+    thr = np.array(threshold)
+
+    confidence = np.ones(b31.shape)
+
+    if thr[4] == 1:
+        print('11-4um diff test running')
+        confidence = conf.conf_test(b31-b20, thr)
+
+    return np.minimum(cmin, confidence.reshape(radshape))
+
+
+def vis_nir_ratio_test(rad1, rad2, threshold, sg_threshold, cmin):
+    print("NIR-Visible ratio test running")
+    if threshold['vis_nir_ratio'][6] == 1:
+
+        radshape = rad1.shape
+        rad1 = rad1.reshape(np.prod(radshape))
+        rad2 = rad2.reshape(np.prod(radshape))
+
+        vrat = rad2/rad1
+
+        thresh = np.zeros((7,))
+
+        # temp value to avoid linter bitching at me
+        # eventually we would have the test run in two blocks as:
+        # confidence[sunglint == 1] = conf.conf_test_dble(vrat[sunglint == 1], sg_threshold['snglnt'])
+        # confidence[sunglint == 0] = conf.conf_test_dble(vrat[sunglint == 0], threshold['vis_nir_ratio'])
+        # sunglint needs to be defined somewhere
+        sunglint = 0
+        if sunglint:
+            thresh = threshold['snglnt']
+        else:
+            thresh = threshold['vis_nir_ratio']
+
+        confidence = conf.conf_test_dble(vrat, thresh)
+
+        return np.minimum(cmin, confidence.reshape(radshape))
+
+
+def nir_refl_test(rad, threshold, sunglint_thresholds, viirs_data, cmin):
+
+    print("NIR reflectance test running")
+    sza = viirs_data.solar_zenith.values
+    refang = viirs_data.sunglint_angle.values
+    vza = viirs_data.sensor_zenith.values
+    dtr = np.pi/180
+    # Keep in mind that band_n uses MODIS band numbers (i.e. 2=0.86um and 7=2.1um)
+    # For VIIRS would be 2=M07 (0.865um) and 7=M11 (2.25um)
+    band_n = 2
+    vzcpow = 0.75  # THIS NEEDS TO BE READ FROM THE THRESHOLDS FILE
+
+    radshape = rad.shape
+    rad = rad.reshape(np.prod(radshape))
+    confidence = np.ones(rad.shape)
+    sza = sza.reshape(rad.shape)
+    vza = vza.reshape(rad.shape)
+    refang = refang.reshape(rad.shape)
+    sunglint_flag = utils.sunglint_scene(refang, sunglint_thresholds).reshape(rad.shape)
+
+    # ref2 [5]
+    # b2coeffs [4]
+    # b2mid [1]
+    # b2bias_adj [1]
+    # b2lo [1]
+    # vzcpow [3] (in different place)
+
+    cosvza = np.cos(vza*dtr)
+    coeffs = threshold['b2coeffs']
+    hicut0 = np.array(coeffs[0] + coeffs[1]*sza + coeffs[2]*np.power(sza, 2) + coeffs[3]*np.power(sza, 3))
+    hicut0 = (hicut0 * 0.01) + threshold['b2adj']
+    hicut0 = hicut0 * threshold['b2bias_adj']
+    midpt0 = hicut0 + (threshold['b2mid'] * threshold['b2bias_adj'])
+    locut0 = midpt0 + (threshold['b2lo'] * threshold['b2bias_adj'])
+    thr = np.array([locut0, midpt0, hicut0, threshold['ref2'][3]*np.ones(rad.shape)])
+    # corr_thr = np.zeros((4, 4))
+    corr_thr = np.zeros((4, rad.shape[0]))
+
+    corr_thr[:3, sunglint_flag == 0] = thr[:3, sunglint_flag == 0] * (1./np.power(cosvza[sunglint_flag == 0], vzcpow))
+    corr_thr[3, sunglint_flag == 0] = thr[3, sunglint_flag == 0]
+
+    for flag in range(1, 4):
+        if len(refang[sunglint_flag == flag]) > 0:
+            sunglint_thr = utils.get_sunglint_thresholds(refang, sunglint_thresholds, band_n, flag, thr)
+            corr_thr[:3, sunglint_flag == flag] = sunglint_thr[:3, sunglint_flag == flag] * (1./np.power(cosvza[sunglint_flag == flag], vzcpow))
+            corr_thr[3, sunglint_flag == flag] = sunglint_thr[3, sunglint_flag == flag]
+
+    confidence = conf.conf_test(rad, corr_thr)
+
+    return np.minimum(cmin, confidence.reshape(radshape))
+
+
+def nir_high_cloud_test():
+    pass
+
+
+
+
+
+
+
+
+
+
+
+def test_11um_var(rad, threshold, var_threshold):
+
+    print("11um variability test running")
+    thr = np.array(threshold['11um_var'])
+
+    radshape = rad.shape
+    var = np.zeros((radshape[0], radshape[1], 9))
+
+    # chk_spatial2() need to figure out what this is
+    # np = rg_var.num_small_diffs * 1.0
+    test = sliding_window_view(np.pad(rad, [1, 1], mode='constant'), (3, 3)) - np.expand_dims(rad, (2, 3))
+
+    var[np.abs(test).reshape(radshape[0], radshape[1], 9) < var_threshold['dovar11']] = 1
+    var = var.sum(axis=2).reshape(np.prod(radshape))
+
+    rad = rad.reshape(np.prod(radshape))
+    confidence = np.zeros(rad.shape)
+
+    confidence[var == 9] = conf.conf_test(rad[var == 9], thr)
+
+    return confidence.reshape(radshape)
+
+
+def test_11_4diff(rad1, rad2, threshold, viirs_data, sg_thresh):
+
+    print("11um - 4um difference test running")
+    radshape = rad1.shape
+    raddiff = (rad1 - rad2).reshape(np.prod(radshape))
+
+    day = np.zeros(radshape)
+    day[viirs_data.solar_zenith <= 85] = 1
+    day = day.reshape(raddiff.shape)
+    sunglint = np.zeros(rad1.shape)
+    sunglint[viirs_data.sunglint_angle <= sg_thresh] = 1
+    sunglint = sunglint.reshape(raddiff.shape)
+    thr = np.array(threshold['test11_4lo'])
+    confidence = np.zeros(raddiff.shape)
+
+    # confidence[(day == 1) & (sunglint == 0)] = utils.conf_test(raddiff[(day == 1) & (sunglint == 0)], thr)
+    confidence[(day == 1) & (sunglint == 0)] = conf.conf_test(raddiff[(day == 1) & (sunglint == 0)], thr)
+
+    return confidence.reshape(radshape)
+
+
+def vir_refl_test(rad, threshold, viirs_data):
+
+    print('Visible reflectance test running')
+
+    thr = threshold['vis_refl_test']
+
+    radshape = rad.shape()
+    rad = rad.reshape(np.prod(radshape))
+    confidence = np.zeros(radshape)
+    vzcpow = 0.75  # THIS NEEDS TO BE READ FROM THE THRESHOLDS FILE
+
+    vza = viirs_data.sensor_zenith.values
+    dtr = np.pi/180
+    cosvza = np.cos(vza*dtr)
+
+    coeffs = utils.get_b1_thresholds()
+    coeffs[:, :3] = coeffs[:, :3] * threshold['b1_bias_adj']
+
+    # this quantity is the return of get_b1_thresholds() in the C code
+    # it's defined here to keep a consistent logic with the original source, for now
+    irtn = 0
+
+    if irtn != 0:
+        coeffs = thr
+
+    coeffs[:, :3] = coeffs[:, :3] * 1/np.power(cosvza, vzcpow)
+
+    confidence = conf.conf_test(rad, coeffs)
+
+    return confidence.reshape(radshape)
+
+
+
+class CloudMaskTests(object):
+
+    def __init__(self, scene, radiance, coefficients):
+        self.scene = scene
+        self.coefficients = coefficients
+
+    def select_coefficients(self):
+        pass
+
+    def test_G1(self):
+        pass
+
+    def test_G2(self):
+        pass
+
+    def test_G3(self):
+        pass
+
+    def test_G4(self):
+        pass
+
+    def overall_confidence(self):
+        pass
+
+
+def test():
+    rad = np.random.randint(50, size=[4, 8])
+    # coeffs = [5, 42, 20, 28, 15, 35, 1]
+    # coeffs = [20, 28, 5, 42, 15, 35, 1]
+    coeffs = [35, 15, 20, 1, 1]
+    # confidence = conf_test_dble(rad, coeffs)
+    confidence = test_11um(rad, coeffs)
+    print(rad)
+    print('\n')
+    print(confidence)
+
+
+if __name__ == "__main__":
+    test()
+
+
+
+
+
+
diff --git a/read_data.py b/read_data.py
index e0b7088..864f3d1 100644
--- a/read_data.py
+++ b/read_data.py
@@ -72,7 +72,7 @@ def correct_reflectances():
 def read_ancillary_data(file_names, viirs_data):
 
     # Ancillary files temporarily defined here. Eventually we will find a better way to pass these
-    start_time = '2022-06-22 03:36:00.000'
+    start_time = '2022-06-22 14:54:00.000'
     anc_dir = file_names['ANC_DIR']
     sst_file = file_names['SST']
     ndvi_file = file_names['NDVI']
diff --git a/tests.py b/tests.py
index 044b206..7a5edd7 100644
--- a/tests.py
+++ b/tests.py
@@ -6,6 +6,8 @@ import utils
 import conf
 
 
+# ############## GROUP 1 TESTS ############## #
+
 def test_11um(rad, threshold):
 
     radshape = rad.shape
diff --git a/utils.py b/utils.py
index 7f90e49..6b45056 100644
--- a/utils.py
+++ b/utils.py
@@ -32,7 +32,7 @@ def get_sunglint_thresholds(refang, thresholds, band_n, sunglint_flag, thr):
 
     # if refang <= thresholds['bounds'][1]:
     if sunglint_flag == 3:
-        sunglint_thr = np.full((4, len(refang)), thresholds[f'{band}_0deg'])
+        sunglint_thr = np.full((len(refang), 4), thresholds[f'{band}_0deg']).T
         # sunglint_thr[:, :] = thresholds[f'{band}_0deg']
 
     else:
-- 
GitLab