From 0502262d60e306a4a5418745bdac357273c0d39a Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Wed, 10 May 2023 13:51:44 -0600 Subject: [PATCH] Feature #2523 dim_order (#2524) --- docs/Users_Guide/tc-rmw.rst | 8 +-- src/libcode/vx_tc_util/vx_tc_nc_util.cc | 67 +++++++++---------- src/libcode/vx_tc_util/vx_tc_nc_util.h | 2 +- .../tc_utils/rmw_analysis/rmw_analysis.cc | 50 +++++++------- src/tools/tc_utils/tc_rmw/tc_rmw.cc | 67 +++++++++---------- 5 files changed, 93 insertions(+), 101 deletions(-) diff --git a/docs/Users_Guide/tc-rmw.rst b/docs/Users_Guide/tc-rmw.rst index 766d9a4d7b..29e0e3be07 100644 --- a/docs/Users_Guide/tc-rmw.rst +++ b/docs/Users_Guide/tc-rmw.rst @@ -166,12 +166,12 @@ tc_rmw output file The NetCDF output file contains the following dimensions: -1. *range* - the radial dimension of the range-azimuth grid +1. *track_point* - the track points corresponding to the model output valid times -2. *azimuth* - the azimuthal dimension of the range-azimuth grid +2. *pressure* - if any pressure levels are specified in the data variable list, they will be sorted and combined into a 3D NetCDF variable, which pressure as the vertical dimension and range and azimuth as the horizontal dimensions -3. *pressure* - if any pressure levels are specified in the data variable list, they will be sorted and combined into a 3D NetCDF variable, which pressure as the vertical dimension and range and azimuth as the horizontal dimensions +3. *range* - the radial dimension of the range-azimuth grid -4. *track_point* - the track points corresponding to the model output valid times +4. *azimuth* - the azimuthal dimension of the range-azimuth grid For each data variable specified in the data variable list, a corresponding NetCDF variable will be created with the same name and units. diff --git a/src/libcode/vx_tc_util/vx_tc_nc_util.cc b/src/libcode/vx_tc_util/vx_tc_nc_util.cc index c6eb467491..2cde15bce3 100644 --- a/src/libcode/vx_tc_util/vx_tc_nc_util.cc +++ b/src/libcode/vx_tc_util/vx_tc_nc_util.cc @@ -271,22 +271,25 @@ void def_tc_range_azimuth(NcFile* nc_out, //////////////////////////////////////////////////////////////////////// -void def_tc_lat_lon_time(NcFile* nc_out, - const NcDim& range_dim, const NcDim& azimuth_dim, - const NcDim& track_point_dim, - NcVar& lat_var, NcVar& lon_var, NcVar& valid_time_var) { +void def_tc_time_lat_lon(NcFile* nc_out, + const NcDim& track_point_dim, const NcDim& range_dim, const NcDim& azimuth_dim, + NcVar& valid_time_var, NcVar& lat_var, NcVar& lon_var) { vector dims; + dims.push_back(track_point_dim); dims.push_back(range_dim); dims.push_back(azimuth_dim); - dims.push_back(track_point_dim); - lat_var = nc_out->addVar("lat", ncDouble, dims); - lon_var = nc_out->addVar("lon", ncDouble, dims); valid_time_var = nc_out->addVar("valid_time", ncUint64, track_point_dim); + lat_var = nc_out->addVar("lat", ncDouble, dims); + lon_var = nc_out->addVar("lon", ncDouble, dims); // Set attributes + add_att(&valid_time_var, "long_name", "valid_time"); + add_att(&valid_time_var, "units", "yyyymmddhh"); + add_att(&valid_time_var, "standard_name", "valid_time"); + add_att(&lat_var, "long_name", "latitude"); add_att(&lat_var, "units", "degrees_north"); add_att(&lat_var, "standard_name", "latitude"); @@ -294,10 +297,6 @@ void def_tc_lat_lon_time(NcFile* nc_out, add_att(&lon_var, "long_name", "longitude"); add_att(&lon_var, "units", "degrees_east"); add_att(&lon_var, "standard_name", "longitude"); - - add_att(&valid_time_var, "long_name", "valid_time"); - add_att(&valid_time_var, "units", "yyyymmddhh"); - add_att(&valid_time_var, "standard_name", "valid_time"); } //////////////////////////////////////////////////////////////////////// @@ -324,20 +323,20 @@ void def_tc_variables(NcFile* nc_out, map > variable_levels, map variable_long_names, map variable_units, + const NcDim& track_point_dim, const NcDim& pressure_dim, const NcDim& range_dim, const NcDim& azimuth_dim, - const NcDim& pressure_dim, const NcDim& track_point_dim, map& data_vars) { vector dims; + dims.push_back(track_point_dim); dims.push_back(range_dim); dims.push_back(azimuth_dim); - dims.push_back(track_point_dim); vector dims_3d; + dims_3d.push_back(track_point_dim); + dims_3d.push_back(pressure_dim); dims_3d.push_back(range_dim); dims_3d.push_back(azimuth_dim); - dims_3d.push_back(pressure_dim); - dims_3d.push_back(track_point_dim); for (map >::iterator i = variable_levels.begin(); i != variable_levels.end(); ++i) { @@ -373,9 +372,9 @@ void def_tc_data(NcFile* nc_out, NcVar& data_var, VarInfo* data_info) { vector dims; + dims.push_back(track_point_dim); dims.push_back(range_dim); dims.push_back(azimuth_dim); - dims.push_back(track_point_dim); ConcatString var_name = data_info->name_attr(); var_name.add("_"); @@ -398,10 +397,10 @@ void def_tc_data_3d(NcFile* nc_out, NcVar& data_var, VarInfo* data_info) { vector dims; + dims.push_back(track_point_dim); + dims.push_back(pressure_dim); dims.push_back(range_dim); dims.push_back(azimuth_dim); - dims.push_back(pressure_dim); - dims.push_back(track_point_dim); data_var = nc_out->addVar( data_info->name_attr(), ncDouble, dims); @@ -420,8 +419,8 @@ void def_tc_azi_mean_data(NcFile* nc_out, NcVar& data_var, VarInfo* data_info) { vector dims; - dims.push_back(range_dim); dims.push_back(track_point_dim); + dims.push_back(range_dim); ConcatString var_name = data_info->name_attr(); var_name.add("_"); @@ -445,14 +444,14 @@ void write_tc_data(NcFile* nc_out, const TcrmwGrid& grid, vector counts; offsets.clear(); + offsets.push_back(i_point); offsets.push_back(0); offsets.push_back(0); - offsets.push_back(i_point); counts.clear(); + counts.push_back(1); counts.push_back(grid.range_n()); counts.push_back(grid.azimuth_n()); - counts.push_back(1); var.putVar(offsets, counts, data); } @@ -468,14 +467,14 @@ void write_tc_data_rev(NcFile* nc_out, const TcrmwGrid& grid, double* data_rev; offsets.clear(); + offsets.push_back(i_point); offsets.push_back(0); offsets.push_back(0); - offsets.push_back(i_point); counts.clear(); + counts.push_back(1); counts.push_back(grid.range_n()); counts.push_back(grid.azimuth_n()); - counts.push_back(1); data_rev = new double[ grid.range_n() * grid.azimuth_n()]; @@ -505,12 +504,12 @@ void write_tc_azi_mean_data(NcFile* nc_out, const TcrmwGrid& grid, double* data_azi_mean; offsets.clear(); - offsets.push_back(0); offsets.push_back(i_point); + offsets.push_back(0); counts.clear(); - counts.push_back(grid.range_n()); counts.push_back(1); + counts.push_back(grid.range_n()); data_rev = new double[ grid.range_n() * grid.azimuth_n()]; @@ -554,26 +553,26 @@ extern void write_tc_pressure_level_data( int i_level = pressure_level_indices[level_str]; offsets.clear(); + offsets.push_back(i_point); offsets.push_back(0); offsets.push_back(0); - offsets.push_back(i_point); offsets_3d.clear(); + offsets_3d.push_back(i_point); + offsets_3d.push_back(i_level); offsets_3d.push_back(0); offsets_3d.push_back(0); - offsets_3d.push_back(i_level); - offsets_3d.push_back(i_point); counts.clear(); + counts.push_back(1); counts.push_back(grid.range_n()); counts.push_back(grid.azimuth_n()); - counts.push_back(1); counts_3d.clear(); - counts_3d.push_back(grid.range_n()); - counts_3d.push_back(grid.azimuth_n()); counts_3d.push_back(1); counts_3d.push_back(1); + counts_3d.push_back(grid.range_n()); + counts_3d.push_back(grid.azimuth_n()); data_rev = new double[ grid.range_n() * grid.azimuth_n()]; @@ -586,12 +585,6 @@ extern void write_tc_pressure_level_data( } } - // string label = level_str.substr(0, 1); - // if (label == "P") { - // var.putVar(offsets_3d, counts_3d, data_rev); - // } else { - // var.putVar(offsets, counts, data_rev); - // } var.putVar(offsets_3d, counts_3d, data_rev); delete[] data_rev; diff --git a/src/libcode/vx_tc_util/vx_tc_nc_util.h b/src/libcode/vx_tc_util/vx_tc_nc_util.h index 32ea30ad63..d909cffe83 100644 --- a/src/libcode/vx_tc_util/vx_tc_nc_util.h +++ b/src/libcode/vx_tc_util/vx_tc_nc_util.h @@ -47,7 +47,7 @@ extern void def_tc_pressure(netCDF::NcFile*, extern void def_tc_range_azimuth(netCDF::NcFile*, const netCDF::NcDim&, const netCDF::NcDim&, const TcrmwGrid&, double); -extern void def_tc_lat_lon_time(netCDF::NcFile*, +extern void def_tc_time_lat_lon(netCDF::NcFile*, const netCDF::NcDim&, const netCDF::NcDim&, const netCDF::NcDim&, netCDF::NcVar&, netCDF::NcVar&, netCDF::NcVar&); diff --git a/src/tools/tc_utils/rmw_analysis/rmw_analysis.cc b/src/tools/tc_utils/rmw_analysis/rmw_analysis.cc index 1a5f9ea899..b3206ce23f 100644 --- a/src/tools/tc_utils/rmw_analysis/rmw_analysis.cc +++ b/src/tools/tc_utils/rmw_analysis/rmw_analysis.cc @@ -198,8 +198,8 @@ void setup() { } mlog << Debug(2) - << "(n_range, n_azimuth, n_level) = (" - << n_range << ", " << n_azimuth << ", " << n_level << ")\n"; + << "(n_level, n_range, n_azimuth) = (" + << n_level << ", " << n_range << ", " << n_azimuth << ")\n"; // Get dimension coordinates vector start; @@ -255,11 +255,11 @@ void setup() { DataCube* data_max_2d = new DataCube(); DataCube* data_min_2d = new DataCube(); - data_count_2d->set_size(n_range, n_azimuth, 1); - data_mean_2d->set_size(n_range, n_azimuth, 1); - data_stdev_2d->set_size(n_range, n_azimuth, 1); - data_max_2d->set_size(n_range, n_azimuth, 1); - data_min_2d->set_size(n_range, n_azimuth, 1); + data_count_2d->set_size(1, n_range, n_azimuth); + data_mean_2d->set_size(1, n_range, n_azimuth); + data_stdev_2d->set_size(1, n_range, n_azimuth); + data_max_2d->set_size(1, n_range, n_azimuth); + data_min_2d->set_size(1, n_range, n_azimuth); data_count_2d->set_constant(0); data_mean_2d->set_constant(0); @@ -281,11 +281,11 @@ void setup() { DataCube* data_max_3d = new DataCube(); DataCube* data_min_3d = new DataCube(); - data_count_3d->set_size(n_range, n_azimuth, n_level); - data_mean_3d->set_size(n_range, n_azimuth, n_level); - data_stdev_3d->set_size(n_range, n_azimuth, n_level); - data_max_3d->set_size(n_range, n_azimuth, n_level); - data_min_3d->set_size(n_range, n_azimuth, n_level); + data_count_3d->set_size(n_level, n_range, n_azimuth); + data_mean_3d->set_size(n_level, n_range, n_azimuth); + data_stdev_3d->set_size(n_level, n_range, n_azimuth); + data_max_3d->set_size(n_level, n_range, n_azimuth); + data_min_3d->set_size(n_level, n_range, n_azimuth); data_count_3d->set_constant(0); data_mean_3d->set_constant(0); @@ -312,10 +312,10 @@ void process_files() { DataCube data_3d; DataCube data_3d_sq; - data_2d.set_size(n_range, n_azimuth, 1); - data_2d_sq.set_size(n_range, n_azimuth, 1); - data_3d.set_size(n_range, n_azimuth, n_level); - data_3d_sq.set_size(n_range, n_azimuth, n_level); + data_2d.set_size(1, n_range, n_azimuth); + data_2d_sq.set_size(1, n_range, n_azimuth); + data_3d.set_size(n_level, n_range, n_azimuth); + data_3d_sq.set_size(n_level, n_range, n_azimuth); // Set up array track point slices vector start_2d; @@ -325,17 +325,17 @@ void process_files() { start_2d.push_back(0); start_2d.push_back(0); start_2d.push_back(0); + count_2d.push_back(1); count_2d.push_back(n_range); count_2d.push_back(n_azimuth); - count_2d.push_back(1); start_3d.push_back(0); start_3d.push_back(0); start_3d.push_back(0); start_3d.push_back(0); + count_3d.push_back(1); + count_3d.push_back(n_level); count_3d.push_back(n_range); count_3d.push_back(n_azimuth); - count_3d.push_back(n_level); - count_3d.push_back(1); for(int i_file = 0; i_file < data_files.n_elements(); i_file++) { mlog << Debug(1) << "Processing " @@ -362,7 +362,7 @@ void process_files() { for(int i_track = 0; i_track < n_track_point; i_track++) { if (data_n_dims[i_var] == 2) { - start_2d[2] = (size_t) i_track; + start_2d[0] = (size_t) i_track; mlog << Debug(4) << data_names[i_var] << i_track << "\n"; var.getVar(start_2d, count_2d, data_2d.data()); @@ -387,7 +387,7 @@ void process_files() { } if (data_n_dims[i_var] == 3) { mlog << Debug(4) << data_names[i_var] << i_track << "\n"; - start_3d[3] = (size_t) i_track; + start_3d[0] = (size_t) i_track; var.getVar(start_3d, count_3d, data_3d.data()); // Update partial sums @@ -442,22 +442,22 @@ void write_stats() { dims_2d.push_back(azimuth_dim); vector dims_3d; + dims_3d.push_back(level_dim); dims_3d.push_back(range_dim); dims_3d.push_back(azimuth_dim); - dims_3d.push_back(level_dim); + NcVar level_var = nc_out->addVar(level_name, ncDouble, level_dim); NcVar range_var = nc_out->addVar("range", ncDouble, range_dim); NcVar azimuth_var = nc_out->addVar("azimuth", ncDouble, azimuth_dim); - NcVar level_var = nc_out->addVar(level_name, ncDouble, level_dim); vector offset; vector count_range; vector count_azimuth; vector count_level; offset.push_back(0); + count_level.push_back(n_level); count_range.push_back(n_range); count_azimuth.push_back(n_azimuth); - count_level.push_back(n_level); for (int r = 0; r < n_range; r++) { range_coord[r] = r; @@ -485,9 +485,9 @@ void write_stats() { offset_3d.push_back(0); offset_3d.push_back(0); offset_3d.push_back(0); + count_3d.push_back(n_level); count_3d.push_back(n_range); count_3d.push_back(n_azimuth); - count_3d.push_back(n_level); for(int i_var = 0; i_var < data_names.size(); i_var++) { if (data_n_dims[i_var] == 2) { diff --git a/src/tools/tc_utils/tc_rmw/tc_rmw.cc b/src/tools/tc_utils/tc_rmw/tc_rmw.cc index 39a8be0529..4dd6a5f2dc 100644 --- a/src/tools/tc_utils/tc_rmw/tc_rmw.cc +++ b/src/tools/tc_utils/tc_rmw/tc_rmw.cc @@ -18,6 +18,7 @@ // 001 05/15/20 Halley Gotway Fix data file list option logic. // 002 07/06/22 Howard Soh METplus-Internal #19 Rename main to met_main // 003 09/28/22 Prestopnik MET #2227 Remove namspace std and netCDF from header files +// 004 04/26/23 Halley Gotway MET #2523 Reorder NetCDF dimensions // //////////////////////////////////////////////////////////////////////// @@ -168,7 +169,7 @@ void process_command_line(int argc, char **argv) { // Add function calls for arguments cline.add(set_data_files, "-data", -1); cline.add(set_deck, "-deck", -1); - // Queitly support -adeck option for backward compatibility with met-9.0 + // Quietly support -adeck option for backward compatibility with met-9.0 cline.add(set_deck, "-adeck", -1); cline.add(set_config, "-config", 1); cline.add(set_out, "-out", 1); @@ -575,35 +576,36 @@ void setup_nc_file() { << ", Azimuth = " << tcrmw_grid.azimuth_n() << "\n"; // Define dimensions + track_point_dim = add_dim(nc_out, "track_point", NC_UNLIMITED); range_dim = add_dim(nc_out, "range", (long) tcrmw_grid.range_n()); azimuth_dim = add_dim(nc_out, "azimuth", (long) tcrmw_grid.azimuth_n()); - track_point_dim = add_dim(nc_out, "track_point", NC_UNLIMITED); // Define range and azimuth dimensions def_tc_range_azimuth(nc_out, range_dim, azimuth_dim, tcrmw_grid, conf_info.rmw_scale); // Define latitude and longitude arrays - def_tc_lat_lon_time(nc_out, range_dim, azimuth_dim, - track_point_dim, lat_arr_var, lon_arr_var, valid_time_var); + def_tc_time_lat_lon(nc_out, + track_point_dim, range_dim, azimuth_dim, + valid_time_var, lat_arr_var, lon_arr_var); // Find all variable levels, long names, and units for(int i_var = 0; i_var < conf_info.get_n_data(); i_var++) { // Get VarInfo data_info = conf_info.data_info[i_var]; mlog << Debug(4) << "Processing field: " << data_info->magic_str() << "\n"; - string fname = data_info->name_attr(); + string fname = data_info->name_attr(); variable_levels[fname].push_back(data_info->level_attr()); variable_long_names[fname] = data_info->long_name_attr(); variable_units[fname] = data_info->units_attr(); - wind_converter.update_input(fname, data_info->units_attr()); + wind_converter.update_input(fname, data_info->units_attr()); } // Define pressure levels pressure_level_strings = get_pressure_level_strings(variable_levels); pressure_levels = get_pressure_levels(pressure_level_strings); - pressure_level_indices - = get_pressure_level_indices(pressure_level_strings, pressure_levels); + pressure_level_indices = + get_pressure_level_indices(pressure_level_strings, pressure_levels); pressure_dim = add_dim(nc_out, "pressure", pressure_levels.size()); def_tc_pressure(nc_out, pressure_dim, pressure_levels); @@ -611,7 +613,7 @@ void setup_nc_file() { def_tc_variables(nc_out, variable_levels, variable_long_names, variable_units, - range_dim, azimuth_dim, pressure_dim, track_point_dim, + track_point_dim, pressure_dim, range_dim, azimuth_dim, data_3d_vars); } @@ -628,7 +630,7 @@ void compute_lat_lon(TcrmwGrid& tcrmw_grid, tcrmw_grid.range_azi_to_latlon( ir * tcrmw_grid.range_delta_km(), ia * tcrmw_grid.azimuth_delta_deg(), - lat, lon); + lat, lon); lat_arr[i] = lat; lon_arr[i] = - lon; } @@ -638,7 +640,6 @@ void compute_lat_lon(TcrmwGrid& tcrmw_grid, //////////////////////////////////////////////////////////////////////// void process_fields(const TrackInfoArray& tracks) { - VarInfo *data_info = (VarInfo *) 0; DataPlane data_dp; @@ -695,14 +696,13 @@ void process_fields(const TrackInfoArray& tracks) { // Update the variable info with the valid time of the track point data_info = conf_info.data_info[i_var]; - string sname = data_info->name_attr().string(); - string slevel = data_info->level_attr().string(); + string sname = data_info->name_attr().string(); + string slevel = data_info->level_attr().string(); - data_info->set_valid(valid_time); + data_info->set_valid(valid_time); // Find data for this track point - get_series_entry(i_point, data_info, data_files, ftype, data_dp, - latlon_arr); + get_series_entry(i_point, data_info, data_files, ftype, data_dp, latlon_arr); // Check data range double data_min, data_max; @@ -711,32 +711,31 @@ void process_fields(const TrackInfoArray& tracks) { mlog << Debug(4) << "data_max:" << data_max << "\n"; // Regrid data - data_dp = met_regrid(data_dp, - latlon_arr, grid, data_info->regrid()); - data_dp.data_range(data_min, data_max); + data_dp = met_regrid(data_dp, latlon_arr, grid, data_info->regrid()); + data_dp.data_range(data_min, data_max); mlog << Debug(4) << "data_min:" << data_min << "\n"; mlog << Debug(4) << "data_max:" << data_max << "\n"; - // if this is "U", setup everything for matching "V" and compute the radial/tangential - if (wind_converter.compute_winds_if_input_is_u(i_point, sname, slevel, valid_time, data_files, ftype, - latlon_arr, lat_arr, lon_arr, grid, data_dp, tcrmw_grid)) - { - write_tc_pressure_level_data(nc_out, tcrmw_grid, - pressure_level_indices, data_info->level_attr(), i_point, - data_3d_vars[conf_info.radial_velocity_field_name.string()], - wind_converter.get_wind_r_arr()); - write_tc_pressure_level_data(nc_out, tcrmw_grid, - pressure_level_indices, data_info->level_attr(), i_point, - data_3d_vars[conf_info.tangential_velocity_field_name.string()], - wind_converter.get_wind_t_arr()); - } + // if this is "U", setup everything for matching "V" and compute the radial/tangential + if(wind_converter.compute_winds_if_input_is_u(i_point, sname, slevel, valid_time, data_files, ftype, + latlon_arr, lat_arr, lon_arr, grid, data_dp, tcrmw_grid)) { + write_tc_pressure_level_data(nc_out, tcrmw_grid, + pressure_level_indices, data_info->level_attr(), i_point, + data_3d_vars[conf_info.radial_velocity_field_name.string()], + wind_converter.get_wind_r_arr()); + write_tc_pressure_level_data(nc_out, tcrmw_grid, + pressure_level_indices, data_info->level_attr(), i_point, + data_3d_vars[conf_info.tangential_velocity_field_name.string()], + wind_converter.get_wind_t_arr()); + } // Write data - if (variable_levels[data_info->name_attr()].size() > 1) { + if(variable_levels[data_info->name_attr()].size() > 1) { write_tc_pressure_level_data(nc_out, tcrmw_grid, pressure_level_indices, data_info->level_attr(), i_point, data_3d_vars[data_info->name_attr()], data_dp.data()); - } else { + } + else { write_tc_data_rev(nc_out, tcrmw_grid, i_point, data_3d_vars[data_info->name_attr()], data_dp.data()); }