From 0b4589ef3d9f2846067c82826d8427d2716bda37 Mon Sep 17 00:00:00 2001 From: tomrink <rink@ssec.wisc.edu> Date: Sat, 25 Dec 2021 14:02:47 -0600 Subject: [PATCH] initial commit --- modules/amv/caliop_clavrx_amv.py | 276 +++++++++++++++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 modules/amv/caliop_clavrx_amv.py diff --git a/modules/amv/caliop_clavrx_amv.py b/modules/amv/caliop_clavrx_amv.py new file mode 100644 index 00000000..84283401 --- /dev/null +++ b/modules/amv/caliop_clavrx_amv.py @@ -0,0 +1,276 @@ +import numpy as np +import xarray as xr +from netCDF4 import Dataset +from aeolus.datasource import get_datasource, CLAVRx_CALIPSO + +amv_file_duration = 60 # minutes +half_width = 50 # search box centered on AEOLUS profile (FGF coordinates) +num_elems = 5424 +num_lines = 5424 + + +def get_search_box(cc, ll): + + c_rng = [cc - half_width, cc + half_width] + l_rng = [ll - half_width, ll + half_width] + + if c_rng[0] < 0: + c_rng[0] = 0 + + if l_rng[0] < 0: + l_rng[0] = 0 + + if c_rng[1] >= num_elems: + c_rng[1] = num_elems - 1 + + if l_rng[1] >= num_lines: + l_rng[1] = num_lines - 1 + + return c_rng, l_rng + + +def match_calipso_clavrx_to_amvs(calipso_clavrx_path, calipso_clavrx_file, amv_files_path, amv_source='OPS', band='14', amv_files=None): + if amv_files is None: + amv_files = get_datasource(amv_files_path, amv_source, band=band) + nav = amv_files.get_navigation() + amv_params = amv_files.get_parameters() + all_params = [amv_files.lon_name, amv_files.lat_name, amv_files.elem_name, amv_files.line_name] + amv_params + match_dict = {} + coords = {'num_params': all_params} + dims = ['num_params', 'num_amvs'] + + calipso_clavrx_ds = CLAVRx_CALIPSO(calipso_clavrx_path) + + nom_time = calipso_clavrx_ds.get_datetime(calipso_clavrx_file).timestamp() + calipso_clavrx_nc4 = Dataset(calipso_clavrx_file) + + fname, ftime, f_idx = amv_files.get_file_containing_time(nom_time) + if f_idx is None: + return + + match_dict[nom_time] = [] + + amv_ds = Dataset(fname) + amv_lons = amv_ds[amv_files.lon_name][:] + amv_lats = amv_ds[amv_files.lat_name][:] + if amv_files.elem_name is not None: + amv_cc = amv_ds[amv_files.elem_name][:] + amv_ll = amv_ds[amv_files.line_name][:] + else: + amv_cc, amv_ll = nav.earth_to_lc_s(amv_lons, amv_lats) + + param_s = [] + param_s.append(amv_lons) + param_s.append(amv_lats) + param_s.append(amv_cc) + param_s.append(amv_ll) + for param in amv_params: + if param == 'V_3D': + param_s.append(amv_ds[param][:, 0]) + param_s.append(amv_ds[param][:, 1]) + else: + param_s.append(amv_ds[param][:]) + + amv_ds.close() + + calipso_clavrx_params = ['closest_calipso_top_alt', 'closest_calipso_base_alt', 'cld_height_acha', 'cld_height_base_acha'] + coords_a = {'num_calipso_clavrx_params': calipso_clavrx_params} + dims_a = ['num_calipso_clavrx_params'] + calipso_clavrx_data = [] + for pname in calipso_clavrx_params: + calipso_clavrx_data.append(calipso_clavrx_nc4[pname][:]) + lat_s = calipso_clavrx_nc4['latitude'][:] + lon_s = calipso_clavrx_nc4['longitude'][:] + xs = calipso_clavrx_nc4['x'][:] + ys = calipso_clavrx_nc4['y'][:] + clvr_xy_s = zip(xs, ys) + + for idx, clvr_xy in enumerate(clvr_xy_s): + cc, ll = clvr_xy + + c_rng, l_rng = get_search_box(cc, ll) + + in_cc = np.logical_and(amv_cc > c_rng[0], amv_cc < c_rng[1]) + in_ll = np.logical_and(amv_ll > l_rng[0], amv_ll < l_rng[1]) + in_box = np.logical_and(in_cc, in_ll) + + num_amvs = np.sum(in_box) + if num_amvs == 0: + continue + # dist = haversine_np(lon, lat, amv_lons[in_box], amv_lats[in_box]) + param_nd = np.vstack(param_s) + param_nd = param_nd[:, in_box] + amvs_da = xr.DataArray(param_nd, coords=coords, dims=dims) + + data_nd = np.vstack(calipso_clavrx_data) + data_da = xr.DataArray(data_nd[:, idx], coords=coords_a, dims=dims_a) + + match_dict[nom_time].append((cc, ll, lon_s[idx], lat_s[idx], f_idx, data_da, amvs_da)) + + return match_dict + + +def create_file_new(match_dct, filename, amv_params=['pressure', 'wind_speed', 'wind_direction'], + caliop_clavrx_params=['closest_calipso_top_alt', 'closest_calipso_base_alt', 'cld_height_acha', 'cld_height_base_acha']): + num_aparams = 7 + num_aprofs = 0 + max_num_alevels = 0 + max_num_amvs = 0 + + alons = [] + alats = [] + atimes = [] + elems = [] + lines = [] + fidxs = [] + + #amv_file_s = np.array(amv_file_s, dtype='object') + + # scan to get max num levels, amvs + keys = list(match_dct.keys()) + for key in keys: + tup_s = match_dct.get(key) + for tup in tup_s: + num_aprofs += 1 + atimes.append(key) + elems.append(tup[0]) + lines.append(tup[1]) + alons.append(tup[2]) + alats.append(tup[3]) + fidxs.append(tup[4]) + + amvs = tup[6] + num_amvs = amvs.shape[1] + if num_amvs > max_num_amvs: + max_num_amvs = num_amvs + + alons = np.array(alons) + alats = np.array(alats) + atimes = np.array(atimes) + elems = np.array(elems) + lines = np.array(lines) + fidxs = np.array(fidxs) + + # Sample file to retrieve and copy variable attributes + # rg_exmpl = Dataset('/ships19/cloud/scratch/4TH_AMV_INTERCOMPARISON/FMWK2_AMV/GOES16_ABI_2KM_FD_2019293_0020_34_WINDS_AMV_EN-14CT.nc', 'r') + rg_exmpl = Dataset('/ships19/cloud/scratch/AMV_FAST_BIAS/OPS_AMVS/OR_ABI-L2-DMWF-M6C14_G16_s20201050000166_e20201050009474_c20201050023226.nc') + + caliop_clavrx_exmpl = Dataset('/data/Personal/rink/clavrx_calipso/g16_s20201050200_06kmCLay.matchup.calipso.h5', 'r') + + # the top level group for the output file + rootgrp = Dataset(filename, 'w', format='NETCDF4') + + #dim_aparams = rootgrp.createDimension('num_aeolus_params', size=num_aparams) + #dim_alevs = rootgrp.createDimension('max_num_aeolus_levels', size=max_num_alevels) + dim_amvs = rootgrp.createDimension('max_num_amvs', size=max_num_amvs) + dim_num_aeolus_prof = rootgrp.createDimension('num_caliop_profs', size=num_aprofs) + #dim_num_files = rootgrp.createDimension('num_amv_files', size=amv_file_s.shape[0]) + + prf_time = rootgrp.createVariable('time', 'f4', ['num_caliop_profs']) + #amv_file_names = rootgrp.createVariable('amv_file_names', str, ['num_amv_files']) + + # ---- Profile variables --------------- + prf_lon = rootgrp.createVariable('prof_longitude', 'f4', ['num_caliop_profs']) + prf_lon.units = 'degrees east' + prf_lat = rootgrp.createVariable('prof_latitude', 'f4', ['num_caliop_profs']) + prf_lat.units = 'degrees north' + prf_time.units = 'seconds since 1970-01-1 00:00:00' + prf_elem = rootgrp.createVariable('FD_elem', 'f4', ['num_caliop_profs']) + prf_line = rootgrp.createVariable('FD_line', 'f4', ['num_caliop_profs']) + prf_fidx = rootgrp.createVariable('amv_file_index', 'i4', ['num_caliop_profs']) + + # ----- CALIOP+CLAVRx variables ------ + nc4_vars_cc = [] + var_s = caliop_clavrx_exmpl.variables + for pidx, param in enumerate(caliop_clavrx_params): + v = var_s[param] + attr_s = v.ncattrs() + if '_FillValue' in attr_s: + var = rootgrp.createVariable(param, v.dtype, ['num_caliop_profs'], fill_value=v.getncattr('_FillValue')) + else: + var = rootgrp.createVariable(param, v.dtype, ['num_caliop_profs']) + # copy attributes from example to new output variable of the same name + for attr in attr_s: + if attr != '_FillValue': + var.setncattr(attr, v.getncattr(attr)) + nc4_vars_cc.append(var) + + # ----- AMV variables ---------------- + nc4_vars = [] + var_s = rg_exmpl.variables + for pidx, param in enumerate(amv_params): + v = var_s[param] + attr_s = v.ncattrs() + if '_FillValue' in attr_s: + var = rootgrp.createVariable(param, v.dtype, ['num_caliop_profs', 'max_num_amvs'], fill_value=v.getncattr('_FillValue')) + else: + var = rootgrp.createVariable(param, v.dtype, ['num_caliop_profs', 'max_num_amvs']) + # copy attributes from example to new output variable of the same name + for attr in attr_s: + if attr != '_FillValue': + var.setncattr(attr, v.getncattr(attr)) + nc4_vars.append(var) + + # Write data to file --------------------- + prf_lon[:] = alons + prf_lat[:] = alats + prf_elem[:] = elems + prf_line[:] = lines + prf_time[:] = atimes + prf_fidx[:] = fidxs + + #amv_file_names[:] = amv_file_s + + idx = 0 + for key in keys: + tup_s = match_dct.get(key) + for tup in tup_s: + data_nd = tup[5] + amvs_nd = tup[6] + + for pidx, param in enumerate(caliop_clavrx_params): + nda = data_nd[pidx] + nc4_vars_cc[pidx][idx] = nda + + for pidx, param in enumerate(amv_params): + nda = amvs_nd[pidx+4,] + cnt = nda.shape[0] + nc4_vars[pidx][idx, 0:cnt] = nda + idx += 1 + + rg_exmpl.close() + rootgrp.close() + + +# def run_clavrx_to_aeolus_match(aeolus_files_dir, clvrx_files_dir, outfile, chan='mie'): +# if os.path.isdir(aeolus_files_dir): +# a_dct = get_aeolus_time_dict_s(aeolus_files_dir, chan=chan) +# else: +# a_dct = get_aeolus_time_dict(aeolus_files_dir) +# +# a_dct = time_dict_to_nd(a_dct) +# clvrx_files = CLAVRx(clvrx_files_dir) +# m_d = match_aeolus_to_clavrx(a_dct, clvrx_files) +# create_aeolus_clavrx_match_file(m_d, outfile, clvrx_files.get_parameters(), clvrx_files.flist) +# +# +# # aeolus_files_dir: S4 NOAA txt output files +# # amv_files_dir: G16/17 AMV product files +# # outfile: pathname for the Netcdf match file +# def create_amv_to_aeolus_match_file(aeolus_files_dir, amv_files_dir, outfile, amv_source='OPS', band='14', chan='mie'): +# +# if os.path.isdir(aeolus_files_dir): +# a_d = get_aeolus_time_dict_s(aeolus_files_dir, chan=chan) +# else: +# a_d = get_aeolus_time_dict(aeolus_files_dir) +# a_d = time_dict_to_nd(a_d) +# +# amv_files = None +# if amv_source == 'CARR': +# amv_files = get_datasource(amv_files_dir, 'CARR', file_time_span=60, band=band) +# else: +# amv_files = get_datasource(amv_files_dir, amv_source, band=band) +# +# m_d = match_amvs_to_aeolus_fast(a_d, amv_files_dir, amv_source, band, amv_files) +# +# create_file_new(m_d, outfile, amv_files.get_parameters(), amv_files.flist) -- GitLab