Skip to content
Snippets Groups Projects
scene.py 17.3 KiB
Newer Older
import ruamel_yaml as yml

from glob import glob

import read_data as rd
_scene_list = ['ocean_day', 'ocean_night', 'land_day', 'land_night', 'snow_day', 'snow_night', 'coast_day',
               'desert_day', 'antarctic_day', 'polar_day_snow', 'polar_day_desert', 'polar_day_ocean',
               'polar_day_desert_coast', 'polar_day_coast', 'polar_day_land', 'polar_night_snow',
               'polar_night_land', 'polar_night_ocean', 'land_day_desert_coast']
_flags = ['day', 'night', 'land', 'coast', 'sh_lake', 'sh_ocean', 'water', 'polar', 'sunglint',
          'greenland', 'high_elevation', 'antarctica', 'desert', 'visusd', 'vrused', 'map_snow', 'map_ice',
          'ndsi_snow', 'snow', 'ice', 'new_zealand']

# temp value, need to verify what the actual bad_data value is in the C code
_bad_data = -999.0
# I'm defining here the flags for difference scenes. Eventually I want to find a better way of doing this
land = 1
sh_lake = .3
sh_ocean = .4
water = 5
polar = 60
sunglint = 70
day = 100
night = 200

# #################################################################### #
# TEST CASE
# data:
datapath = '/ships19/hercules/pveglio/mvcm_viirs_hires'
fname_mod02 = glob(f'{datapath}/VNP02MOD.A2022173.1448.001.*.uwssec.nc')[0]
fname_mod03 = glob(f'{datapath}/VNP03MOD.A2022173.1448.001.*.uwssec.nc')[0]
fname_img02 = glob(f'{datapath}/VNP02IMG.A2022173.1448.001.*.uwssec.nc')[0]
fname_img03 = glob(f'{datapath}/VNP03IMG.A2022173.1448.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_1500.V01.nc4'
geos_atm_2 = 'GEOS.fpit.asm.inst3_2d_asm_Nx.GEOS5124.20220622_1800.V01.nc4'
geos_land = 'GEOS.fpit.asm.tavg1_2d_lnd_Nx.GEOS5124.20220622_1630.V01.nc4'
geos_ocean = 'GEOS.fpit.asm.tavg1_2d_ocn_Nx.GEOS5124.20220622_1630.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'

# #################################################################### #


def test_scene():

    ancillary_file_names = {'GEOS_atm_1': geos_atm_1,
                            'GEOS_atm_2': geos_atm_2,
                            'GEOS_land': geos_land,
                            'GEOS_ocean': geos_ocean,
                            'GEOS_constants': geos_constants,
                            'NDVI': ndvi_file,
                            'SST': sst_file,
                            'ANC_DIR': f'{datapath}/ancillary'
                            }

    viirs_data = rd.read_data('viirs', f'{fname_mod02}', f'{fname_mod03}')

    viirs_data = rd.read_ancillary_data(ancillary_file_names, viirs_data)

    with open(threshold_file) as f:
        text = f.read()
    thresholds = yml.safe_load(text)

    sunglint_angle = thresholds['Sun_Glint']['bounds'][3]

    scene = find_scene(viirs_data, sunglint_angle)

    return scene

    eco = data['eco'].values
    lsf = data['land_water_mask'].values
    lat = data['latitude'].values
    lon = data['longitude'].values
    sza = data['solar_zenith'].values
    vza = data['sensor_zenith'].values
    raz = data['relative_azimuth'].values
    b065 = data['M05'].values
    b086 = data['M07'].values
    elev = data['height'].values
    ndvibk = data['ndvi'].values
    sfctmp = data['geos_sfct'].values

    dim1 = data.latitude.shape[0]
    dim2 = data.latitude.shape[1]
    day = np.zeros((dim1, dim2))
    day[sza <= 85] = 1
    cos_refang = np.sin(vza*_dtr) * np.sin(sza*_dtr) * np.cos(raz*_dtr) + np.cos(vza*_dtr) * np.cos(sza*_dtr)
    refang = np.arccos(cos_refang) * _rtd
    # tmp = np.ones((dim1, dim2))
    # tmp[day == 1] = day
    # tmp[day == 0] = night
    scene_flag = {flg: np.zeros((dim1, dim2)) for flg in _flags}

    scene_flag['day'][sza <= 85] = 1
    scene_flag['visusd'][sza <= 85] = 1
    scene_flag['night'][sza > 85] = 1

    # ################# need to pass refang (once I figure out what it is) and sunglint_angle. The latter
    # comes from the thresholds file. In the C code is snglnt_bounds[3]
    idx = np.nonzero((scene_flag['day'] == 1) & (refang <= sunglint_angle))
    scene_flag['sunglint'][idx] = 1

    # Force consistency between lsf and ecosystem type for water
    idx = np.nonzero((lsf == 0) | (lsf >= 5) & (lsf < 7))
    eco[idx] = 14

    # start by defining anythings as land
    scene_flag['land'] = np.ones((dim1, dim2))
    scene_flag['water'] = np.zeros((dim1, dim2))

    # Fix-up for missing ecosystem data in eastern Greenland and north-eastern Siberia.
    # Without this, these regions become completely "coast".
    idx = np.nonzero((lsf != 255) & (lsf == 1) | (lsf == 4))
    scene_flag['land'][idx] = 1

    idx = np.nonzero((lsf != 255) & (eco == 14) & (lsf == 1) | (lsf == 4) & (lat < 64.0))
    scene_flag['coast'][idx] = 1

    idx = np.nonzero((lsf != 255) & (eco == 14) & (lsf == 1) | (lsf == 4) &
                     (lat >= 67.5) & (lon < -40.0) & (lon > -168.6))
    scene_flag['coast'][idx] = 1
    idx = np.nonzero((lsf != 255) & (eco == 14) & (lsf == 1) | (lsf == 4) &
                     (lat >= 67.5) & (lon > -12.5))
    scene_flag['coast'][idx] = 1

    idx = np.nonzero((lsf != 255) & (eco == 14) & (lsf == 1) | (lsf == 4) &
                     (lat >= 64.0) & (lat < 67.5) & (lon < -40.0) & (lon > -168.5))
    scene_flag['coast'][idx] = 1
    idx = np.nonzero((lsf != 255) & (eco == 14) & (lsf == 1) | (lsf == 4) &
                     (lat >= 64.0) & (lat < 67.5) & (lon > -30.0))
    scene_flag['coast'][idx] = 1

    idx = np.nonzero(lsf == 2)
    scene_flag['coast'][idx] = 1
    scene_flag['land'][idx] = 1

    idx = np.nonzero(lsf == 3)
    scene_flag['land'][idx] = 1
    scene_flag['sh_lake'][idx] = 1

    idx = np.nonzero((lsf == 0) | (lsf >= 5) & (lsf <= 7))
    scene_flag['water'][idx] = 1
    scene_flag['land'][idx] = 0

    scene_flag['sh_ocean'][lsf == 0] = 1

    # Need shallow lakes to be processed as "coast" for day, but not night
    idx = np.nonzero((lsf == 3) & (day == 1))
    scene_flag['coast'][idx] = 1

    # if land/sea flag is missing, then calculate visible ratio to determine if land or water.
    idx = np.nonzero((lsf == 255) & (b065 != _bad_data) & (b086 != _bad_data) & (b086/b065 > 0.9))

    idx = np.nonzero((lsf == 255) & (b065 != _bad_data) & (b086 != _bad_data) & (b086/b065 <= 0.9))
    scene_flag['land'][idx] = 0
    scene_flag['water'][idx] = 1

    # Check surface elevation
    # First, define "Greenland".
    idx = np.nonzero((scene_flag['land'] == 1) &
                     (lat >= 60.0) & (lat < 67.0) & (lon >= -60.0) & (lon < -30.0))
    scene_flag['greenland'][idx] = 1

    idx = np.nonzero((scene_flag['land'] == 1) &
                     (lat >= 67.0) & (lat < 75.0) & (lon >= -60.0) & (lon < -10.0))
    scene_flag['greenland'][idx] = 1

    idx = np.nonzero((scene_flag['land'] == 1) &
                     (lat >= 75.0) & (lon >= -70.0) & (lon < -10.0))
    scene_flag['greenland'][idx] = 1

    scene_flag['high_elevation'][elev > 2000] = 1
    idx = np.nonzero((elev > 200) & (scene_flag['greenland'] == 1) & (scene_flag['land'] == 1))
    scene_flag['high_elevation'][idx] = 1

    idx = np.nonzero((lat >= 75.0) & (lat <= 79.0) & (lon >= -73.0) & (lon <= -50.0) &
                     (scene_flag['land'] == 1))
    scene_flag['high_elevation'][idx] = 1

    scene_flag['antarctica'][lat < -60.0] = 1

    #  somewhere here I need to add  #
    #  the 11um elevation correction #
    # this is a temporary variable for the 11um elevation correction
    elev_correction = elev/1000.0 * 5.0
    ## Get surface temperature from NWP and SST fields
    ## if it's land get it from GDAS/GEOS5
    #sfctmp[scene_flag['land'] == 1] = sfct
    ## otherwise use the ReynoldsSST
    #sfctmp[scene_flag['land'] == 0] = reynSST
    # Use background NDVI to define "desert"
    idx = np.nonzero((scene_flag['land'] == 1) & (ndvibk < 0.3))
    scene_flag['desert'][idx] = 1
    idx = np.nonzero((scene_flag['land'] == 1) & (lat < -69.0))
    scene_flag['desert'][idx] = 1
    idx = np.nonzero((eco == 2) | (eco == 8) | (eco == 11) | (eco == 40) | (eco == 41) | (eco == 46) |
                     (eco == 51) | (eco == 52) | (eco == 59) | (eco == 71) | (eco == 50))
    scene_flag['vrused'][idx] = 0

    snow_fraction = data['geos_snowfr']
    perm_ice_fraction = data['geos_landicefr']
    ice_fraction = data['geos_icefr']

    idx = np.nonzero((snow_fraction > 0.10) & (snow_fraction <= 1.0))

    idx = np.nonzero((perm_ice_fraction > 0.10) & (perm_ice_fraction <= 1.0))
    scene_flag['map_snow'][idx] = 1

    idx = np.nonzero((ice_fraction > 0.10) & (ice_fraction <= 1.0))
    scene_flag['map_ice'][idx] = 1

    # need to define this function and write this block better
    # if day == 1:
    #    # Run quick version of D. Hall's snow detection algorithm
    #    # Temporarily disabled because this function does not exist and I need to decide how to implement it
    #    # scene_flag['ndsi_snow'] = run_snow_mask()
    #     scene_flag['ndsi_snow'] = np.zeros((dim1, dim2))

    idx = np.nonzero((day == 1) & (water == 1) & (lat >= -60.0) & (lat <= 25.0) &
                     (scene_flag['map_snow'] == 1) & (scene_flag['ndsi_snow'] == 1))
    scene_flag['ice'][idx] = 1

    idx = np.nonzero((day == 1) & (water == 1) & (lat < -60.0) &
                     (scene_flag['ndsi_snow'] == 1))
    scene_flag['ice'][idx] = 1

    idx = np.nonzero((day == 1) & (water == 1) & (lsf == 3) | (lsf == 5) &
                     (scene_flag['ndsi_snow'] == 1))
    scene_flag['ice'][idx] = 1

    idx = np.nonzero((day == 1) & (water == 1) &
                     (scene_flag['map_ice'] == 1) & (scene_flag['ndsi_snow'] == 1))
    scene_flag['ice'][idx] = 1

    # Define New Zealand region which receives snow but snow map does not show it.
    idx = np.nonzero((day == 1) & (land == 1) &
                     (lat >= 48.0) & (lat <= -34.0) & (lon >= 165.0) & (lon <= 180.0))

    idx = np.nonzero((day == 1) & (land == 1) & (lat >= -60.0) & (lat <= 25.0) &
                     (scene_flag['map_snow'] == 1) & (scene_flag['ndsi_snow'] == 1) |
                     (scene_flag['new_zealand'] == 1))
    scene_flag['snow'][idx] = 1

    idx = np.nonzero((day == 1) & (land == 1) & (lat < -60.0))

    idx = np.nonzero((day == 1) & (land == 1) & (scene_flag['ndsi_snow'] == 1))

    idx = np.nonzero((day == 0) & (scene_flag['map_snow'] == 1) &
                     (sfctmp > 280.0) & (elev < 500.0))
    scene_flag['snow'][idx] = 0

    idx = np.nonzero((day == 0) & (scene_flag['map_snow'] == 1) &
                     (sfctmp > 280.0) & (elev < 500.0))
    scene_flag['ice'][idx] = 0

    idx = np.nonzero((day == 0) & (lat > 86.0))

    ##################################
    #      CONTINUE FROM HERE        #
    ##################################
    # Check regional uniformity
    # Check for data border pixels
    # NEED TO UNDERSTAND WHAT THIS PART DOES

    # TEMP VALUES FOR DEBUGGING
    scene_flag['lat'] = lat
    scene_flag['lon'] = lon

    return scene_flag
def scene_id(scene_flag):

    dim1, dim2 = scene_flag['day'].shape[0], scene_flag['day'].shape[1]
    scene = {scn: np.zeros((dim1, dim2)) for scn in _scene_list}
    # Ocean Day
    idx = np.nonzero((scene_flag['water'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['coast'] == 0) & (scene_flag['desert'] == 0))
    scene['ocean_day'][idx] = 1

    # Ocean Night
    idx = np.nonzero((scene_flag['water'] == 1) & (scene_flag['night'] == 1) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['coast'] == 0) & (scene_flag['desert'] == 0))
    scene['ocean_night'][idx] = 1

    # Land Day
    idx = np.nonzero((scene_flag['land'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['coast'] == 0) & (scene_flag['desert'] == 0))
    scene['land_day'][idx] = 1

    # Land Night
    idx = np.nonzero((scene_flag['land'] == 1) & (scene_flag['night'] == 1) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['coast'] == 0))
    scene['land_night'][idx] = 1

    # Snow Day
    idx = np.nonzero((scene_flag['day'] == 1) &
                     ((scene_flag['ice'] == 1) | (scene_flag['snow'] == 1)) &
                     (scene_flag['polar']) & (scene_flag['antarctica']))
    scene['snow_day'][idx] = 1

    # Snow Night
    idx = np.nonzero((scene_flag['night'] == 1) &
                     ((scene_flag['ice'] == 1) | (scene_flag['snow'] == 1)) &
                     (scene_flag['polar']) & (scene_flag['antarctica']))
    scene['snow_night'][idx] = 1

    # Land Day Coast
    idx = np.nonzero((scene_flag['land'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['coast'] == 1) & (scene_flag['desert'] == 0) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0))
    scene['land_day_coast'][idx] = 1

    # Land Day Desert
    idx = np.nonzero((scene_flag['land'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['desert'] == 1) & (scene_flag['coast'] == 0) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0))
    scene['desert_day'][idx] = 1

    # Land Day Desert Coast
    idx = np.nonzero((scene_flag['land'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['desert'] == 1) & (scene_flag['coast'] == 1) &
                     (scene_flag['polar'] == 0) & (scene_flag['antarctica'] == 0))
    scene['land_day_desert_coast'][idx] = 1

    # Antarctic Day
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['antarctica'] == 1) & (scene_flag['land'] == 1))
    scene['antarctic_day'][idx] = 1

    # Polar Day Snow
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     ((scene_flag['snow'] == 1) | (scene_flag['ice'] == 1)) &
                     (scene_flag['antarctica'] == 0))
    scene['polar_day_snow'][idx] = 1

    # Polar Day Desert
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['land'] == 1) & (scene_flag['desert'] == 1) &
                     (scene_flag['coast'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0))
    scene['polar_day_desert'][idx] = 1

    # Polar Day Desert Coast
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['land'] == 1) & (scene_flag['desert'] == 1) &
                     (scene_flag['coast'] == 1) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0))
    scene['polar_day_desert_coast'][idx] = 1

    # Polar Day Coast
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['land'] == 1) & (scene_flag['coast'] == 1)
                     (scene_flag['desert'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0))
    scene['polar_day_coast'][idx] = 1

    # Polar Day Land
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['land'] == 1) & (scene_flag['coast'] == 0)
                     (scene_flag['desert'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0))
    scene['polar_day_land'][idx] = 1

    # Polar Day Ocean
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['day'] == 1) &
                     (scene_flag['water'] == 1) & (scene_flag['coast'] == 0)
                     (scene_flag['desert'] == 0) & (scene_flag['antarctica'] == 0) &
                     (scene_flag['ice'] == 0) & (scene_flag['snow'] == 0))
    scene['polar_day_land'][idx] = 1

    # Polar Night Snow
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['night'] == 1) &
                     ((scene_flag['snow'] == 1) | (scene_flag['ice'] == 1)))
    scene['polar_night_snow'][idx] = 1

    # Polar Night Land
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['night'] == 1) &
                     (scene_flag['land'] == 1))
    scene['polar_night_land'][idx] = 1

    # Polar Night Ocean
    idx = np.nonzero((scene_flag['polar'] == 1) & (scene_flag['night'] == 1) &
                     (scene_flag['water'] == 1))
    scene['polar_night_ocean'][idx] = 1

    return scene
    scene['polar_day_ocean'][idx] = 1