diff --git a/.github/jobs/set_job_controls.sh b/.github/jobs/set_job_controls.sh index 3cb1389658..54aeca8507 100755 --- a/.github/jobs/set_job_controls.sh +++ b/.github/jobs/set_job_controls.sh @@ -17,9 +17,11 @@ if [ "${GITHUB_EVENT_NAME}" == "pull_request" ]; then run_diff=true - # if base branch starts with main_v, use that input data + # if pull request into main_vX.Y branch, + # set truth data version to branch name and set input data version to X.Y if [ "${GITHUB_BASE_REF:0:6}" == "main_v" ]; then - input_data_version=${GITHUB_BASE_REF:6} + truth_data_version=${GITHUB_BASE_REF} + input_data_version=${GITHUB_BASE_REF:6} fi fi @@ -35,9 +37,9 @@ elif [ "${GITHUB_EVENT_NAME}" == "push" ]; then run_diff=true truth_data_version=${branch_name:0: -4} - # if branch starts with main_v, use that input data + # if main_vX.Y-ref branch, use X.Y input data if [ "${branch_name:0:6}" == "main_v" ]; then - input_data_version=${branch_name:6:-4} + input_data_version=${branch_name:6: -4} fi else @@ -46,10 +48,10 @@ elif [ "${GITHUB_EVENT_NAME}" == "push" ]; then if [ "$branch_name" == "develop" ] || [ "${branch_name:0:6}" == "main_v" ]; then - run_diff=true - truth_data_version=${branch_name} + run_diff=true + truth_data_version=${branch_name} - # if branch starts with main_v, use that input data + # if main_vX.Y branch, use X.Y input data if [ "${branch_name:0:6}" == "main_v" ]; then input_data_version=${branch_name:6} fi @@ -59,24 +61,24 @@ elif [ "${GITHUB_EVENT_NAME}" == "push" ]; then # check commit messages for skip or force keywords if grep -q "ci-skip-all" <<< "$commit_msg"; then - run_compile=false - run_push=false - run_unit_tests=false - run_diff=false - run_update_truth=false + run_compile=false + run_push=false + run_unit_tests=false + run_diff=false + run_update_truth=false fi # check commit messages for ci-skip or ci-run keywords if grep -q "ci-skip-compile" <<< "$commit_msg"; then - run_compile=false + run_compile=false fi if grep -q "ci-run-unit" <<< "$commit_msg"; then - run_diff=true + run_diff=true fi @@ -84,9 +86,9 @@ elif [ "${GITHUB_EVENT_NAME}" == "push" ]; then elif [ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]; then - if [ "${force_tests}" == "true" ]; then - run_diff=true - fi + if [ "${force_tests}" == "true" ]; then + run_diff=true + fi fi diff --git a/met/src/basic/vx_config/config_util.cc b/met/src/basic/vx_config/config_util.cc index e08ef7d19b..fa2f777307 100644 --- a/met/src/basic/vx_config/config_util.cc +++ b/met/src/basic/vx_config/config_util.cc @@ -690,6 +690,9 @@ void parse_sid_mask(const ConcatString &mask_sid_str, } + // Sort the mask_sid's + mask_sid.sort(); + return; } diff --git a/met/src/basic/vx_log/string_array.cc b/met/src/basic/vx_log/string_array.cc index 59539bdf5b..95f110b7eb 100644 --- a/met/src/basic/vx_log/string_array.cc +++ b/met/src/basic/vx_log/string_array.cc @@ -135,6 +135,8 @@ MaxLength = 0; clear(); +Sorted = false; + return; } @@ -149,6 +151,8 @@ void StringArray::clear() s.clear(); +Sorted = false; + return; } @@ -166,6 +170,7 @@ clear(); s = a.s; IgnoreCase = a.IgnoreCase; +Sorted = a.Sorted; return; @@ -183,6 +188,7 @@ Indent prefix(depth); Indent prefix2(depth + 1); out << prefix << "IgnoreCase = " << IgnoreCase << "\n"; +out << prefix << "Sorted = " << (Sorted ? "true" : "false") << "\n"; int j; @@ -250,6 +256,8 @@ void StringArray::add(const std::string text) s.push_back(text); +Sorted = false; + return; } @@ -265,7 +273,9 @@ void StringArray::add(const StringArray & a) if ( a.n() == 0 ) return; s.insert(s.end(), a.s.begin(), a.s.end()); - + +Sorted = false; + return; } @@ -298,6 +308,8 @@ void StringArray::add_css(const std::string text) } + Sorted = false; + return; } @@ -314,6 +326,9 @@ s.clear(); s.push_back(text); +// Setting to a single value, by nature it is Sorted +Sorted = true; + return; } @@ -336,6 +351,8 @@ void StringArray::set(int i, const std::string text) s[i] = text; +Sorted = false; + return; } @@ -358,6 +375,8 @@ void StringArray::insert(int i, const char * text) s.insert(s.begin()+i, text); + Sorted = false; + return; } @@ -366,90 +385,104 @@ void StringArray::insert(int i, const char * text) //////////////////////////////////////////////////////////////////////// -bool StringArray::has(const std::string text, bool forward) const +bool StringArray::has(const std::string text) const { + bool found = false; + bool forward = true; + + if (Sorted && !IgnoreCase) { + found = binary_search(s.begin(), s.end(), text); +} +else { + return ( has(text, forward) ); +} - int index; + return found; +} - return ( has(text, index, forward) ); -} +//////////////////////////////////////////////////////////////////////// + + +bool StringArray::has(const std::string text, bool forward) const +{ + int index; + return ( has(text, index, forward) ); +} //////////////////////////////////////////////////////////////////////// bool StringArray::has(const std::string text, int & index, bool forward) const - { - bool found = false; - index = -1; - - if (!s.empty()) { - int count; - std::string lower_text = text; - std::vector::const_iterator it; - if ( IgnoreCase ) transform(lower_text.begin(), lower_text.end(), lower_text.begin(), ::tolower); - - if (forward) { - count = 0; - for(it = s.begin(); it != s.end(); it++, count++) { - if ( IgnoreCase ) { - std::string lower_s = *it; - transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); - if ( lower_s == lower_text) { - // if ( strcasecmp((*it).c_str(), text.c_str()) ) { - found = true; - break; - } - } - else { - if ( *it == text ) { - found = true; - break; - } - } - } - } - else { - count = s.size() - 1; - it = s.end(); - for(it--; it != s.begin(); it--, count--) { - if ( IgnoreCase ) { - std::string lower_s = *it; - transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); - if ( lower_s == lower_text) { - found = true; - break; - } - } - else { - if ( *it == text ) { - found = true; - break; - } - } + // This function is now used for either an un-sorted array (Sorted is false) + // Or for a case-insensitive search (IgnoreCase is true) + // + bool found = false; + index = -1; + + if (!s.empty()) { + int count; + std::string lower_text = text; + std::vector::const_iterator it; + if ( IgnoreCase ) transform(lower_text.begin(), lower_text.end(), lower_text.begin(), ::tolower); + + if (forward) { + count = 0; + for(it = s.begin(); it != s.end(); it++, count++) { + if ( IgnoreCase ) { + std::string lower_s = *it; + transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); + if ( lower_s == lower_text) { + found = true; + break; + } + } + else { + if ( *it == text ) { + found = true; + break; + } + } + } } - if (!found && it == s.begin()) { - if ( IgnoreCase ) { - std::string lower_s = *it; - transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); - found = ( lower_s == lower_text ); - } - else found = ( *it == text ); + else { + count = s.size() - 1; + it = s.end(); + for(it--; it != s.begin(); it--, count--) { + if ( IgnoreCase ) { + std::string lower_s = *it; + transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); + if ( lower_s == lower_text) { + found = true; + break; + } + } + else { + if ( *it == text ) { + found = true; + break; + } + } + } + if (!found && it == s.begin()) { + if ( IgnoreCase ) { + std::string lower_s = *it; + transform(lower_s.begin(), lower_s.end(), lower_s.begin(), ::tolower); + found = ( lower_s == lower_text ); + } + else found = ( *it == text ); + } } - } - if (found) index = count; - } - //mlog << Debug(9) << " StringArray::has() size=" << s.size() - // << " for " << text << ", found: " << (found ? "true" : "false") - // << ", forward: " << (forward ? "yes" : "no") << "\n"; - - return found; - + if (found) index = count; + } + + return found; } + //////////////////////////////////////////////////////////////////////// @@ -500,6 +533,8 @@ void StringArray::parse_delim(const std::string text, const char *delim) if (start < str.length()) s.push_back(str.substr(start).c_str()); + Sorted = false; + return; } @@ -616,13 +651,19 @@ return ( s[k].length() ); void StringArray::sort() { - -if ( n() <= 1 ) return; - - std::sort(s.begin(), s.end()); - -return; - + if ( n() <= 1 ) { + Sorted = true; + return; + } + + if ( !Sorted ) { + std::sort(s.begin(), s.end()); + } + + Sorted = true; + + return; + } diff --git a/met/src/basic/vx_log/string_array.h b/met/src/basic/vx_log/string_array.h index 22f300b305..9d2aa286e7 100644 --- a/met/src/basic/vx_log/string_array.h +++ b/met/src/basic/vx_log/string_array.h @@ -30,7 +30,6 @@ class StringArray { public: - void init_from_scratch(); void assign(const StringArray &); @@ -40,7 +39,8 @@ class StringArray { int MaxLength; bool IgnoreCase; - + + bool Sorted; public: @@ -77,8 +77,10 @@ class StringArray { int length(int) const; - bool has(const std::string, bool forward=true) const; + bool has(const std::string) const; + bool has(const std::string, bool forward) const; + bool has(const std::string, int & index, bool forward=true) const; // diff --git a/met/src/libcode/vx_data2d_grib/data2d_grib.cc b/met/src/libcode/vx_data2d_grib/data2d_grib.cc index ef5e622b9c..c92e64569a 100644 --- a/met/src/libcode/vx_data2d_grib/data2d_grib.cc +++ b/met/src/libcode/vx_data2d_grib/data2d_grib.cc @@ -762,6 +762,10 @@ bool is_grid_relative(const GribRecord &r) { else if(r.gds->type == 5) { res_flag = r.gds->grid_type.stereographic.res_flag; } + // Rotated LatLon + else if(r.gds->type == 10) { + res_flag = r.gds->grid_type.rot_latlon_grid.res_flag; + } else { mlog << Error << "\nis_grid_relative() -> " << "Unsupported grid type value: " << r.gds->type diff --git a/met/src/libcode/vx_data2d_grib/grib_classes.cc b/met/src/libcode/vx_data2d_grib/grib_classes.cc index da1a5f0f76..d02445c6ef 100644 --- a/met/src/libcode/vx_data2d_grib/grib_classes.cc +++ b/met/src/libcode/vx_data2d_grib/grib_classes.cc @@ -1874,6 +1874,27 @@ else if ((h.type == 5)) file << " scan_flag: " << (int) h.grid_type.stereographic.scan_flag << "\n\n"; } +else if ((h.type == 10)) +{ + + file << " lat1: " << char3_to_int(h.grid_type.rot_latlon_grid.lat1) << "\n"; + file << " lon1: " << char3_to_int(h.grid_type.rot_latlon_grid.lon1) << "\n"; + + file << " res_flag: " << (int) h.grid_type.rot_latlon_grid.res_flag << "\n"; + + file << " lat2: " << char3_to_int(h.grid_type.rot_latlon_grid.lat2) << "\n"; + file << " lon2: " << char3_to_int(h.grid_type.rot_latlon_grid.lon2) << "\n"; + + file << " di: " << char2_to_int(h.grid_type.rot_latlon_grid.di) << "\n"; + file << " dj: " << char2_to_int(h.grid_type.rot_latlon_grid.dj) << "\n"; + + file << " scan_flag: " << (int) h.grid_type.rot_latlon_grid.scan_flag << "\n"; + + file << " lat_sp: " << char3_to_int(h.grid_type.rot_latlon_grid.lat_sp) << "\n"; + file << " lon_sp: " << char3_to_int(h.grid_type.rot_latlon_grid.lon_sp) << "\n"; + + file << " rotation: " << char4_to_dbl(h.grid_type.rot_latlon_grid.rotation) << "\n\n"; +} return ( file ); diff --git a/met/src/libcode/vx_data2d_grib/grib_classes.h b/met/src/libcode/vx_data2d_grib/grib_classes.h index 55b7046d65..3b0295cf45 100644 --- a/met/src/libcode/vx_data2d_grib/grib_classes.h +++ b/met/src/libcode/vx_data2d_grib/grib_classes.h @@ -162,7 +162,7 @@ struct Section1_Header { // PDS //////////////////////////////////////////////////////////////////////// -struct LatLon { // Latitude/Longitude Grid +struct LatLon { // Latitude/Longitude Grid unsigned char lat1[3]; // 11 - 13 unsigned char lon1[3]; // 14 - 16 @@ -179,6 +179,32 @@ struct LatLon { // Latitude/Longitude Grid unsigned char unused[14]; // 29 - 42 +}; + + // Reference: https://apps.ecmwf.int/codes/grib/format/grib1/grids/10 + +struct RotLatLon { // Rotated Latitude/Longitude Grid + + unsigned char lat1[3]; // 11 - 13 + unsigned char lon1[3]; // 14 - 16 + + unsigned char res_flag; // 17 + + unsigned char lat2[3]; // 18 - 20 + unsigned char lon2[3]; // 21 - 23 + + unsigned char di[2]; // 24 - 25 + unsigned char dj[2]; // 26 - 27 + + unsigned char scan_flag; // 28 + + unsigned char unused[4]; // 29 - 32 + + unsigned char lat_sp[3]; // 33 - 35 + unsigned char lon_sp[3]; // 36 - 38 + + unsigned char rotation[4]; // 39 - 42 + }; struct Mercator { // Mercator Grid @@ -282,7 +308,7 @@ struct Gaussian { union GridType { struct LatLon latlon_grid; // Latitude/Longitude Grid - // struct RotLatLon rot_latlon_grid; // Rotated Latitude/Longitude Grid + struct RotLatLon rot_latlon_grid; // Rotated Latitude/Longitude Grid struct Mercator mercator; // Mercator Grid struct LambertConf lambert_conf; // Lambert Conformal Secant Grid struct Stereographic stereographic; // Stereographic Grid diff --git a/met/src/libcode/vx_data2d_grib/grib_utils.cc b/met/src/libcode/vx_data2d_grib/grib_utils.cc index 6dc5b7c563..c1ef70f775 100644 --- a/met/src/libcode/vx_data2d_grib/grib_utils.cc +++ b/met/src/libcode/vx_data2d_grib/grib_utils.cc @@ -29,11 +29,13 @@ using namespace std; // grid types from the GDS section // -static const int latlon_type = 0; -static const int mercator_type = 1; -static const int lambert_type = 3; -static const int stereographic_type = 5; -static const int gaussian_type = 4; +static const int latlon_type = 0; +static const int mercator_type = 1; +static const int lambert_type = 3; +static const int gaussian_type = 4; +static const int stereographic_type = 5; +static const int rotated_latlon_type = 10; + //////////////////////////////////////////////////////////////////////// @@ -62,7 +64,7 @@ void gds_to_grid(const Section2_Header & gds, Grid & gr) LambertData lc_data; StereographicData st_data; LatLonData ll_data; -//RotatedLatLonData rll_data; +RotatedLatLonData rll_data; MercatorData mc_data; GaussianData g_data; @@ -84,11 +86,11 @@ if ( gds.type == latlon_type ) { gr.set(ll_data); -// else if ( gds.type == rotated_latlon_type ) { -// -// gds_to_rotated_latlon(gds, rll_data); -// -// gr.set(rll_data); +} else if ( gds.type == rotated_latlon_type ) { + + gds_to_rotated_latlon(gds, rll_data); + + gr.set(rll_data); } else if ( gds.type == mercator_type ) { @@ -143,6 +145,7 @@ void gds_to_order(const Section2_Header & gds, int & xdir, int & ydir, int & ord // Check GDS for the grid type. // The following Projection types are supported: // - Lat/Lon + // - Rotated Lat/Lon // - Mercator // - Lambert Conformal // - Polar Stereographic @@ -154,6 +157,10 @@ if ( gds.type == latlon_type ) { scan_flag_to_order(gds.grid_type.latlon_grid.scan_flag, xdir, ydir, order); +} else if ( gds.type == rotated_latlon_type ) { + + scan_flag_to_order(gds.grid_type.rot_latlon_grid.scan_flag, xdir, ydir, order); + } else if (gds.type == mercator_type ) { scan_flag_to_order(gds.grid_type.mercator.scan_flag, xdir, ydir, order); @@ -278,10 +285,88 @@ void gds_to_rotated_latlon(const Section2_Header & gds, RotatedLatLonData & data { -mlog << Error << "\ngds_to_rotated_latlon() -> " - << "Rotated Lat/Lon grids are not supported in GRIB version 1.\n\n"; +int xdir, ydir, order; +double d; + +scan_flag_to_order(gds.grid_type.rot_latlon_grid.scan_flag, xdir, ydir, order); + + // Store the grid name +data.name = rotated_latlon_proj_type; + + // + // Multiply longitude values by -1 since the NCAR code considers + // degrees west to be positive. + // + + // Latitude of the bottom left corner +data.rot_lat_ll = min(decode_lat_lon(gds.grid_type.rot_latlon_grid.lat1, 3), + decode_lat_lon(gds.grid_type.rot_latlon_grid.lat2, 3)); + + // Longitude of the bottom left corner +if ( xdir == 0 ) data.rot_lon_ll = -1.0*rescale_lon(decode_lat_lon(gds.grid_type.rot_latlon_grid.lon1, 3)); +else data.rot_lon_ll = -1.0*rescale_lon(decode_lat_lon(gds.grid_type.rot_latlon_grid.lon2, 3)); + + // Number of points in the Latitudinal (y) direction +data.Nlat = char2_to_int(gds.ny); + + // Number of points in the Longitudinal (x) direction +data.Nlon = char2_to_int(gds.nx); + + // Check for thinned lat/lon grids +if ( data.Nlon == 65535 ) { -exit ( 1 ); + mlog << Error << "\ngds_to_rotated_latlon() -> " + << "Thinned Lat/Lon grids are not supported for GRIB version 1.\n\n"; + + exit ( 1 ); + +} + + // Compute latitudinal increment from lat1 and lat2 +d = fabs(decode_lat_lon(gds.grid_type.rot_latlon_grid.lat1, 3) + - decode_lat_lon(gds.grid_type.rot_latlon_grid.lat2, 3)); + +data.delta_rot_lat = d/(data.Nlat); + + // If explicitly specified and non-zero, use it +if ( ! all_bits_set(gds.grid_type.rot_latlon_grid.dj, 2) ) { + + d = decode_lat_lon(gds.grid_type.rot_latlon_grid.dj, 2); + + if ( d > 0 ) data.delta_rot_lat = d; + +} + + // Compute longitudinal increment from lon1 and lon2 +d = fabs(decode_lat_lon(gds.grid_type.rot_latlon_grid.lon1, 3) + - decode_lat_lon(gds.grid_type.rot_latlon_grid.lon2, 3)); + +data.delta_rot_lon = d/(data.Nlon); + + // If explicitly specified and non-zero, use it +if ( ! all_bits_set(gds.grid_type.rot_latlon_grid.di, 2) ) { + + d = decode_lat_lon(gds.grid_type.rot_latlon_grid.di, 2); + + if ( d > 0 ) data.delta_rot_lon = d; + +} + + // Location of (rotated) south pole +data.true_lat_south_pole = + decode_lat_lon(gds.grid_type.rot_latlon_grid.lat_sp, 3); + +data.true_lon_south_pole = + -1.0*rescale_lon(decode_lat_lon(gds.grid_type.rot_latlon_grid.lon_sp, 3)); + + // Auxiliary rotation +data.aux_rotation = char4_to_dbl(gds.grid_type.rot_latlon_grid.rotation); + +data.dump(); + + // + // done + // return; diff --git a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc index 0061d2fd00..65df4c7ef7 100644 --- a/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc +++ b/met/src/libcode/vx_data2d_grib2/data2d_grib2.cc @@ -1100,7 +1100,7 @@ void MetGrib2DataFile::read_grib2_grid( gribfield *gfld) { data.true_lon_south_pole = s_lon; // - // auxilliary rotation around the rotated polar axis + // auxiliary rotation around the rotated polar axis // data.aux_rotation = (t[21])*angle_factor; diff --git a/met/src/libcode/vx_data2d_nc_met/get_met_grid.cc b/met/src/libcode/vx_data2d_nc_met/get_met_grid.cc index 8e9e68cf4d..3512c6aaed 100644 --- a/met/src/libcode/vx_data2d_nc_met/get_met_grid.cc +++ b/met/src/libcode/vx_data2d_nc_met/get_met_grid.cc @@ -309,7 +309,7 @@ data.rot_lon_ll *= -1.0; get_global_att(ncfile, string("true_lon_south_pole"), data.true_lon_south_pole); if ( !west_longitude_positive ) data.true_lon_south_pole *= -1.0; - // auxilliary rotation + // auxiliary rotation get_global_att(ncfile, string("aux_rotation"), data.aux_rotation); diff --git a/met/src/libcode/vx_data2d_nccf/nccf_file.cc b/met/src/libcode/vx_data2d_nccf/nccf_file.cc index dbe5e4e323..7dcb7dc99a 100644 --- a/met/src/libcode/vx_data2d_nccf/nccf_file.cc +++ b/met/src/libcode/vx_data2d_nccf/nccf_file.cc @@ -296,17 +296,15 @@ bool NcCfFile::open(const char * filepath) } // Parse the units for the time variable. + ut = sec_per_unit = 0; NcVarAtt *units_att = get_nc_att(valid_time_var, (string)"units", false); if (IS_VALID_NC_P(units_att)) { - get_att_value_chars(units_att, units); - - if (units.length() == 0) + if (!get_att_value_chars(units_att, units) || units.length() == 0) { mlog << Warning << "\n" << method_name << "the \"time\" variable must contain a \"units\" attribute. " << "Using valid time of 0\n\n"; - ut = sec_per_unit = 0; } else { @@ -315,14 +313,10 @@ bool NcCfFile::open(const char * filepath) parse_cf_time_string(units.c_str(), ut, sec_per_unit); } } - else - { - ut = sec_per_unit = 0; - } + if (units_att) delete units_att; NcVar bounds_time_var; NcVar *nc_time_var = (NcVar *)0; - nc_time_var = valid_time_var; bool use_bounds_var = false; ConcatString bounds_var_name; nc_time_var = valid_time_var; @@ -338,12 +332,12 @@ bool NcCfFile::open(const char * filepath) } if (bounds_att) delete bounds_att; - if (units_att) delete units_att; // Determine the number of times present. int n_times = (int) get_data_size(valid_time_var); int tim_buf_size = n_times; if (use_bounds_var) tim_buf_size *= 2; double *time_values = new double[tim_buf_size]; + if( get_nc_data(nc_time_var, time_values) ) { bool no_leap_year = get_att_no_leap_year(valid_time_var); if( time_dim_count > 1 ) { @@ -375,6 +369,7 @@ bool NcCfFile::open(const char * filepath) } } } + else ValidTime.add(0); //Initialize delete [] time_values; } diff --git a/met/src/libcode/vx_nc_util/nc_utils.cc b/met/src/libcode/vx_nc_util/nc_utils.cc index 8d8e5b1087..0fa9f87df9 100644 --- a/met/src/libcode/vx_nc_util/nc_utils.cc +++ b/met/src/libcode/vx_nc_util/nc_utils.cc @@ -1533,6 +1533,7 @@ bool get_nc_data(NcVar *var, float *data) { // Note: missing data was checked here // int type_id = GET_NC_TYPE_ID_P(var); + return_status = true; if (NcType::nc_FLOAT == type_id) { var->getVar(data); } @@ -1565,9 +1566,26 @@ bool get_nc_data(NcVar *var, float *data) { if (IS_VALID_NC_P(att_scale_factor)) scale_factor = get_att_value_float(att_scale_factor); mlog << Debug(4) << method_name << "add_offset = " << add_offset << ", scale_factor=" << scale_factor << ", cell_count=" << cell_count - << ", is_unsigned_value: " << unsigned_value << "\n"; + << ", is_unsigned_value: " << unsigned_value << " for " << GET_NC_NAME_P(var) << "\n"; switch ( type_id ) { + case NcType::nc_INT64: + { + long long fill_value = bad_data_int; + long long min_value = 2147483647; + long long max_value = -2147483648; + long long *packed_data = new long long[cell_count]; + + if (IS_VALID_NC_P(att_fill_value)) + fill_value = get_att_value_int(att_fill_value); + + var->getVar(packed_data); + _apply_scale_factor(data, packed_data, cell_count, + fill_value, min_value, max_value, "int64", + add_offset, scale_factor); + delete [] packed_data; + } + break; case NcType::nc_INT: { int fill_value = bad_data_int; @@ -1720,15 +1738,15 @@ bool get_nc_data(NcVar *var, float *data) { } break; default: - mlog << Debug(1) << method_name << "type_id: " - << type_id << " type name: " << GET_NC_TYPE_NAME_P(var) - << "\n"; + return_status = false; + mlog << Debug(1) << method_name << "Did not read data because of unsupported data type (" + << type_id << ", type name: " << GET_NC_TYPE_NAME_P(var) + << ") for " << GET_NC_NAME_P(var) << "\n"; } if(att_add_offset) delete att_add_offset; if(att_scale_factor) delete att_scale_factor; if(att_fill_value) delete att_fill_value; } - return_status = true; } mlog << Debug(6) << method_name << "took " @@ -1821,6 +1839,7 @@ bool get_nc_data(NcVar *var, double *data) { // int unpacked_count = 0; int type_id = GET_NC_TYPE_ID_P(var); + return_status = true; if ((NcType::nc_DOUBLE == type_id) || (NcType::nc_FLOAT == type_id)){ var->getVar(data); } @@ -1844,9 +1863,26 @@ bool get_nc_data(NcVar *var, double *data) { } mlog << Debug(4) << method_name << "add_offset = " << add_offset << ", scale_factor=" << scale_factor << ", cell_count=" << cell_count - << ", is_unsigned_value: " << unsigned_value << "\n"; + << ", is_unsigned_value: " << unsigned_value << " for " << GET_NC_NAME_P(var) << "\n"; switch ( type_id ) { + case NcType::nc_INT64: + { + long long fill_value = bad_data_int; + long long min_value = 2147483647; + long long max_value = -2147483648; + long long *packed_data = new long long[cell_count]; + + if (IS_VALID_NC_P(att_fill_value)) + fill_value = get_att_value_int(att_fill_value); + + var->getVar(packed_data); + _apply_scale_factor(data, packed_data, cell_count, + fill_value, min_value, max_value, "int64", + add_offset, scale_factor); + delete [] packed_data; + } + break; case NcType::nc_INT: { int fill_value = bad_data_int; @@ -2001,15 +2037,16 @@ bool get_nc_data(NcVar *var, double *data) { } break; default: - mlog << Debug(1) << method_name << "type_id: " - << type_id << " type name: " << GET_NC_TYPE_NAME_P(var) - << "\n"; + return_status = false; + mlog << Debug(1) << method_name << "Did not read data because of unsupported data type (" + << type_id << ", type name: " << GET_NC_TYPE_NAME_P(var) + << ") for " << GET_NC_NAME_P(var) << "\n"; + } if(att_add_offset) delete att_add_offset; if(att_scale_factor) delete att_scale_factor; if(att_fill_value) delete att_fill_value; } - return_status = true; } return(return_status); } diff --git a/met/src/libcode/vx_statistics/pair_data_point.cc b/met/src/libcode/vx_statistics/pair_data_point.cc index e6366da500..cc8a156ed9 100644 --- a/met/src/libcode/vx_statistics/pair_data_point.cc +++ b/met/src/libcode/vx_statistics/pair_data_point.cc @@ -1142,6 +1142,8 @@ void VxPairDataPoint::add_point_obs(float *hdr_arr, const char *hdr_typ_str, // masking SID list else if(pd[i][j][0].mask_sid_ptr != (StringArray *) 0) { if(!pd[i][j][0].mask_sid_ptr->has(hdr_sid_str)) { + mlog << Debug(9) << "Checking for the obs station id in the masking SID list: rejected hdr_sid_str = " + << hdr_sid_str << "\n"; inc_count(rej_mask, i, j); continue; } diff --git a/met/src/tools/other/ascii2nc/met_handler.cc b/met/src/tools/other/ascii2nc/met_handler.cc index dbb4c4d2a7..cd7c8f2576 100644 --- a/met/src/tools/other/ascii2nc/met_handler.cc +++ b/met/src/tools/other/ascii2nc/met_handler.cc @@ -159,7 +159,7 @@ bool MetHandler::_readObservations(LineDataFile &ascii_file) use_var_id = true; if (!obs_names.has(data_line[6], var_index)) { obs_names.add(data_line[6]); - obs_names.has(data_line[6], var_index); + var_index = obs_names.n() - 1; } grib_code = var_index; break; diff --git a/test/xml/unit_plot_data_plane.xml b/test/xml/unit_plot_data_plane.xml index 3db1b4bfa0..02f85765bc 100644 --- a/test/xml/unit_plot_data_plane.xml +++ b/test/xml/unit_plot_data_plane.xml @@ -88,6 +88,20 @@ + + &MET_BIN;/plot_data_plane + \ + &DATA_DIR_MODEL;/grib1/cosmo/lfff03080000.grib \ + &OUTPUT_DIR;/plot_data_plane/cosmo_rotlatlon_GRIB1_TMP_Z2.ps \ + 'name="T"; level="Z2";' \ + -title "Rotated Lat/Lon 2-meter Temperature" \ + -v 1 + + + &OUTPUT_DIR;/plot_data_plane/cosmo_rotlatlon_GRIB1_TMP_Z2.ps + + + &MET_BIN;/plot_data_plane \ @@ -131,6 +145,22 @@ + + &MET_BIN;/plot_data_plane + \ + &DATA_DIR_MODEL;/grib2/sref_pr/sref_prob_2012040821_F012.grib2 \ + &OUTPUT_DIR;/plot_data_plane/sref_prob_2012040821_F012_GRIB2_PROB_APCP_12_gt2.54.ps \ + 'name = "PROB"; level = "A12"; prob = { name = "APCP"; thresh_lo = 2.54; };' \ + -title "GRIB2 Probability of 12-hour APCP > 2.54mm)" \ + -color_table &MET_BASE;/colortables/NCL_colortables/WhBlGrYeRe.ctable \ + -plot_range 0 100 \ + -v 1 + + + &OUTPUT_DIR;/plot_data_plane/sref_prob_2012040821_F012_GRIB2_PROB_APCP_12_gt2.54.ps + + + &MET_BIN;/plot_data_plane \ @@ -271,33 +301,31 @@ - + &MET_BIN;/plot_data_plane \ - &DATA_DIR_MODEL;/nccf/prods_op_ukv_rotated_latlon_20220301_00_000.nc \ - &OUTPUT_DIR;/plot_data_plane/plot_data_plane_NCCF_rotlatlon.ps \ - 'name="surface_altitude"; level="(*,*)";' \ - -title "Rotated Lat/Lon Surface Altitude" \ + &DATA_DIR_MODEL;/nccf/precipitation_int64_time.nc \ + &OUTPUT_DIR;/plot_data_plane/plot_data_plane_NCCF_int64_time.ps \ + 'name="precipitation"; level="(*,*)";' \ + -title "Observation precipitation" \ -v 1 - &OUTPUT_DIR;/plot_data_plane/plot_data_plane_NCCF_rotlatlon.ps + &OUTPUT_DIR;/plot_data_plane/plot_data_plane_NCCF_int64_time.ps - + &MET_BIN;/plot_data_plane \ - &DATA_DIR_MODEL;/grib2/sref_pr/sref_prob_2012040821_F012.grib2 \ - &OUTPUT_DIR;/plot_data_plane/sref_prob_2012040821_F012_GRIB2_PROB_APCP_12_gt2.54.ps \ - 'name = "PROB"; level = "A12"; prob = { name = "APCP"; thresh_lo = 2.54; };' \ - -title "GRIB2 Probability of 12-hour APCP > 2.54mm)" \ - -color_table &MET_BASE;/colortables/NCL_colortables/WhBlGrYeRe.ctable \ - -plot_range 0 100 \ + &DATA_DIR_MODEL;/nccf/prods_op_ukv_rotated_latlon_20220301_00_000.nc \ + &OUTPUT_DIR;/plot_data_plane/plot_data_plane_NCCF_rotlatlon.ps \ + 'name="surface_altitude"; level="(*,*)";' \ + -title "Rotated Lat/Lon Surface Altitude" \ -v 1 - &OUTPUT_DIR;/plot_data_plane/sref_prob_2012040821_F012_GRIB2_PROB_APCP_12_gt2.54.ps + &OUTPUT_DIR;/plot_data_plane/plot_data_plane_NCCF_rotlatlon.ps