CIMR L2 TSA Processing Chain for the Demonstration Reference Scenario (PICASSO)#

Hide code cell content
import os 
import sys
import numpy as np
import xarray as xr
import pyresample as pr
import importlib
from matplotlib import pyplot as plt
from matplotlib import colors

# local imports
if '/tools/' not in sys.path:
    sys.path.insert(0, os.path.abspath('../.../') + 'algorithm/tools/')
import l2_format as l2
import TSA_algorithm as algorithm
import l2_tools as tools
Hide code cell source
# reload local imports
importlib.reload(l2)
importlib.reload(algorithm)
importlib.reload(tools)
algo = 'Pulliainen2010'
algo_version = '0.9.0'

l1x_scenes = ('devalgo_geometric', 'devalgo_radiometric', 'sceps_polar1')
l2_grids = ('ease2-3.125km-nh','ease2-1.0km-testcard')
# set test_card_name
test_card_name = l1x_scenes[1]      # alternative: test_card_name = l1x_scenes[0]
l2_grid = l2_grids[0]               # nominal L2 product grid
if test_card_name == 'devalgo_geometric':    
    # DEVALGO simulated geometric test card
    l1x_path = os.path.abspath('../../../..../') + 'Data/L1C Files/Geometric/'
    l1x_fn = 'W_PT-DME-Lisbon-SAT-CIMR-1X@KA_C_DME_20230417T105425_LD_20280110T114800_20280110T115700_TN.nc'
elif test_card_name == 'devalgo_radiometric':
    # DEVALGO simulated radiometric test card
    l1x_path = os.path.abspath('../../../..../') + 'Data/L1C Files/Radiometric/'
    l1x_fn = 'W_PT-DME-Lisbon-SAT-CIMR-1X@KA_C_DME_20230420T103323_LD_20280110T114800_20280110T115700_TN.nc'

Step 1: Dry Snow Detection#

# read L1X data
data_fwd,geo_fwd,data_bck,geo_bck = tools.read_l1x(l1x_path + l1x_fn)
# detection forward and backward
TSA_fwd = algorithm.dry_snow_detection(data_fwd,tsa_algorithm=algo)
TSA_bck = algorithm.dry_snow_detection(data_bck,tsa_algorithm=algo)
C:\Users\zschende\OneDrive - Ilmatieteen laitos\Files\Projects\CIMR Devalgo\ATBD\TerrestrialSnowArea_ATBD_v2\algorithm\TSA_algorithm.py:27: FutureWarning: The return type of `Dataset.dims` will be changed to return a set of dimension names in future, in order to be more consistent with `DataArray.dims`. To access a mapping from dimension names to lengths, please use `Dataset.sizes`.
  shp = tuple(data['KA'].dims[d] for d in ['n_scans_interleave_feed','n_samples_earth'])
Hide code cell source
cmap = colors.ListedColormap(['black', 'white'])
vrange=[0,.5,1]
# cmap.set_bad(color='red')

fig, ax = plt.subplots(nrows=1, ncols=2, sharex=True, sharey=False, figsize=(10,10))

img = ax[0].imshow(TSA_fwd, vmin=0, vmax=1, interpolation='none', origin='lower', cmap=cmap)
ax[0].set_title('FORWARD', fontsize='small')
# plt.text(0.01,0.99,'TSA',va='top',color='white')
cbar = plt.colorbar(img, boundaries=vrange, ticks=[0.25, 0.75], orientation='horizontal')
cbar.ax.set_xticklabels(['0', '1'])

img = ax[1].imshow(TSA_bck, vmin=0, vmax=1, interpolation='none', origin='lower', cmap=cmap)
ax[1].set_title('BACKWARD', fontsize='small')
# plt.text(0.01,0.99,'TSA',va='top',color='white')
cbar = plt.colorbar(img, boundaries=vrange, ticks=[0.25, 0.75], orientation='horizontal')
cbar.ax.set_xticklabels(['0', '1'])
    
# fig.savefig('tsa_swath.png', format='png', dpi=1200, bbox_inches='tight')
plt.show()
../_images/0ec11326ea47e83a687f8d7934a37a36efae5433bbb583c107d55884b1639c42.png

Step 2: Combined Reprojection#

Reprojection for nominal TSA product: EASE2 3.125km

Note that for the Algorithm Performance Assessment, the target grid is the same as the Test Card, namely EASE2 1km.

area_def = pr.load_area('ease2_adef.yaml',l2_grid)

cart_crs = area_def.to_cartopy_crs()
# extent = cart_crs.bounds
# trg_lon, trg_lat = area_def.get_lonlats()

Step 2.1: Individual Reprojection#

TSA_fwd_proj = tools.reproject_to_grid(TSA_fwd,geo_fwd,area_def=area_def)
TSA_bck_proj = tools.reproject_to_grid(TSA_bck,geo_bck,area_def=area_def)
Hide code cell source
cmap = colors.ListedColormap(['lightblue', 'tab:blue'])
# cmap.set_bad(color='lightgrey')

vrange = [-0.5,0.5,1.5]
norm = colors.BoundaryNorm(vrange, cmap.N)

fig, ax = plt.subplots(nrows=1, ncols=2, sharex=True, sharey=True, figsize=(10,10),
                       subplot_kw=dict(projection=cart_crs))

img = ax[0].imshow(TSA_fwd_proj, transform=cart_crs, extent=cart_crs.bounds, origin='upper',
              cmap=cmap)
ax[0].coastlines(color='black')
ax[0].set_title('FORWARD', fontsize='small')
ax[0].text(0.01,0.99,'TSA',va='top',transform=ax[0].transAxes)
cbar = plt.colorbar(img, cmap=cmap, norm=norm, boundaries=vrange, ticks=[0,1], orientation='horizontal', pad=0.05, shrink=0.75)
cbar.ax.set_xticklabels(['Snow-free', 'Snow'])

img = ax[1].imshow(TSA_bck_proj, transform=cart_crs, extent=cart_crs.bounds, origin='upper',
              cmap=cmap)
ax[1].coastlines(color='black')
ax[1].set_title('BACKWARD', fontsize='small')
ax[1].text(0.01,0.99,'TSA',va='top',transform=ax[1].transAxes)
cbar = plt.colorbar(img, cmap=cmap, norm=norm, boundaries=vrange, ticks=[0,1], orientation='horizontal', pad=0.05, shrink=0.75)
cbar.ax.set_xticklabels(['Snow-free', 'Snow'])

# plt.savefig('tsa_fwdbck.png', format='png', dpi=1200, bbox_inches='tight')
plt.show()
../_images/bdeb44c320d17c0ddf999ebf3febefd3d9bfd4dc2543ad7cb79fe519ce1c1267.png

Step 2.2: Combining Reprojections#

# intermediate combined data
TSA_comb, TSA_comb_uncert = tools.combine_proj(TSA_fwd_proj,TSA_bck_proj)

Step 3: Masking and Flagging#

# load surface information
if test_card_name == 'devalgo_geometric':
    dem_ref_scenario = os.path.abspath('../../../..../') + 'Data/Test_scenes_downscaled_projected/test_scene_2_compressed_lowres.nc'
elif test_card_name == 'devalgo_radiometric':
    dem_ref_scenario = os.path.abspath('../../../..../') + 'Data/Test_scenes_downscaled_projected/test_scene_1_compressed_lowres.nc'

data_tc = xr.open_dataset(dem_ref_scenario)
swath_def = pr.geometry.SwathDefinition(lons=data_tc['Longitude'].values, lats=data_tc['Latitude'].values)
land_mask = pr.kd_tree.resample_nearest(swath_def, np.float64(data_tc['landflag'].values), area_def,
                        radius_of_influence=20000/4, fill_value=np.nan)

data_tc.close()
# status_flag
TSA_status_flag = np.zeros(TSA_comb.shape, dtype='i8')

TSA_status_flag[TSA_status_flag == 0] = 8                    # 8: no data, out of grid
TSA_status_flag[land_mask == 0] = 0                          # 0: water
TSA_status_flag[(TSA_comb == 0) & (land_mask == 1)] = 1      # 1: land
TSA_status_flag[(TSA_comb == 1) & (land_mask == 1)] = 2      # 2: valid snow
# TSA_status_flag[] = 3                                      # 3: [placeholder]

status_flag_comment = '0: water; 1: land; 2: snow (valid); 3-7: [placeholders]; 8: no data, out of grid.'
# TSA_uncertainty
TSA_uncertainty = np.zeros(TSA_comb.shape, dtype='i8') 

TSA_uncertainty[TSA_comb_uncert == 0] = 0                    # 0: very likely snow-free
TSA_uncertainty[TSA_comb_uncert == 0.5] = 1                  # 1: likely snow
TSA_uncertainty[TSA_comb_uncert == 1] = 2                    # 2: very likely snow
# TSA
TSA_l2 = TSA_comb
# TSA_l2 = np.zeros(TSA_status_flag.shape)

# TSA_l2[TSA_l2 == 0] = np.nan                                 # nan: no data, out of grid
# TSA_l2[TSA_comb == 0] = 0                                    # 0: snow free
# TSA_l2[TSA_comb == 1] = 1                                    # 1: snow covered (dry)
# TSA_l2[TSA_comb == 2] = 2                                    # 2: snow covered (wet) [placeholder]

Visualization of Final Level-2 TSA Variables#

Hide code cell source
TSA_map = TSA_l2.copy()

if test_card_name == 'devalgo_geometric':
    TSA_map_flag = np.zeros(TSA_l2.shape)
    TSA_map_flag[TSA_status_flag == 8] = np.nan
    # TSA_map_flag[TSA_status_flag == 0] = 0                              # water
    TSA_map_flag[(TSA_status_flag == 0) & (TSA_uncertainty == 0)] = 1   # snow-free (very likely)
    TSA_map_flag[(TSA_status_flag == 0) & (TSA_uncertainty == 1)] = 2   # snow cover (likely)
    TSA_map_flag[(TSA_status_flag == 0) & (TSA_uncertainty == 2)] = 3   # snow cover (very likely)

    ax = plt.axes(projection=cart_crs)
    cmap = colors.ListedColormap(['grey', 'skyblue', 'white'])
    vrange=[0.5,1.5,2.5,3.5]
    norm = colors.BoundaryNorm(vrange, cmap.N)

    img = plt.imshow(TSA_map_flag, transform=cart_crs, extent=cart_crs.bounds, origin='upper',
                cmap=cmap)
    ax.coastlines(color='black')
    plt.text(0.01,0.99,'TSA Variables',va='top',transform=ax.transAxes)
    cbar = plt.colorbar(img, cmap=cmap, norm=norm, boundaries=vrange, ticks=[1,2,3], fraction=0.031, pad=0.046)
    cbar.ax.set_yticklabels(['Snow-free\n(high certainty: FWD&BCK)', 'Snow\n(medium certainty: FWD|BCK)', 'Snow\n(high certainty: FWD&BCK)'])

elif test_card_name == 'devalgo_radiometric':
    TSA_map_flag = np.zeros(TSA_l2.shape)
    TSA_map_flag[TSA_status_flag == 8] = np.nan
    TSA_map_flag[TSA_status_flag == 0] = 0                              # water
    TSA_map_flag[(TSA_status_flag == 1) & (TSA_uncertainty == 0)] = 1   # snow-free land (very likely)
    TSA_map_flag[(TSA_status_flag == 2) & (TSA_uncertainty == 1)] = 2   # snow cover (likely)
    TSA_map_flag[(TSA_status_flag == 2) & (TSA_uncertainty == 2)] = 3   # snow cover (very likely)

    ax = plt.axes(projection=cart_crs)
    cmap = colors.ListedColormap(['steelblue', 'grey', 'skyblue', 'white'])
    vrange=[-0.5,0.5,1.5,2.5,3.5]
    norm = colors.BoundaryNorm(vrange, cmap.N)

    img = plt.imshow(TSA_map_flag, transform=cart_crs, extent=cart_crs.bounds, origin='upper',
                cmap=cmap)
    ax.coastlines(color='black')
    plt.text(0.01,0.99,'TSA Variables',va='top',transform=ax.transAxes)
    cbar = plt.colorbar(img, cmap=cmap, norm=norm, boundaries=vrange, ticks=[0,1,2,3], orientation='vertical', pad=0.05, shrink=0.75)
    cbar.ax.set_yticklabels(['Water', 'Snow-free land\n(high certainty: FWD&BCK)', 'Snow cover\n(medium certainty: FWD|BCK)', 'Snow cover\n(high certainty: FWD&BCK)'])

# fig.savefig('tsa_l2product.png', format='png', dpi=2400, bbox_inches='tight')

plt.show()
../_images/a9305040e08b18d6ac5e43cfc74ffa61ac9a31d6d65d715e32c7ffa984ad0631.png