From adfe3986e6122fdbfefd5eb4726aecb952e48a79 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Mon, 21 Aug 2023 09:34:09 -0600 Subject: [PATCH] Update main_v11.1-ref after #2653 (#2656) Co-authored-by: John Halley Gotway Co-authored-by: Seth Linden Co-authored-by: jprestop Co-authored-by: Daniel Adriaansen Co-authored-by: John and Cindy Co-authored-by: Howard Soh Co-authored-by: George McCabe <23407799+georgemccabe@users.noreply.github.com> Co-authored-by: hsoh-u Co-authored-by: MET Tools Test Account Co-authored-by: Seth Linden Co-authored-by: lisagoodrich <33230218+lisagoodrich@users.noreply.github.com> Co-authored-by: davidalbo Co-authored-by: Lisa Goodrich Co-authored-by: metplus-bot <97135045+metplus-bot@users.noreply.github.com> Co-authored-by: j-opatz <59586397+j-opatz@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Jonathan Vigh Co-authored-by: David Albo Co-authored-by: Tracy Hertneky <39317287+hertneky@users.noreply.github.com> Co-authored-by: Dan Adriaansen Fix Python environment issue (#2407) fix definitions of G172 and G220 based on comments in NOAA-EMC/NCEPLIBS-w3emc#157. (#2406) fix #2380 develop override (#2382) fix #2408 develop empty config (#2410) fix #2390 develop compile zlib (#2404) fix #2412 develop climo (#2422) fix #2437 develop convert (#2439) fix for develop, for #2437, forgot one reference to the search_parent for a dictionary lookup. fix #2452 develop airnow (#2454) fix #2449 develop pdf (#2464) fix #2402 develop sonarqube (#2468) fix #2426 develop buoy (#2475) fix 2518 dtypes appf docs (#2519) fix 2531 compilation errors (#2533) fix #2531 compilation_errors_configure (#2535) fix 2596 main v11.1 rpath compilation (#2614) fix #2514 main_v11.1 clang (#2628) fix #2644 main_v11.1 percentile (#2646) --- .github/workflows/testing.yml | 4 +- docs/Users_Guide/appendixB.rst | 4 -- .../config/install_met_env.wcoss2_py3.10 | 6 +-- .../test_unit/xml/unit_plot_data_plane.xml | 14 +++++ src/basic/vx_math/ptile.cc | 49 ++++++++++++++++-- src/libcode/vx_data2d_nccf/data2d_nccf.cc | 23 ++++---- src/libcode/vx_data2d_nccf/nccf_file.cc | 11 +++- src/libcode/vx_grid/.find_grid_by_name.h.swp | Bin 28672 -> 0 bytes 8 files changed, 85 insertions(+), 26 deletions(-) delete mode 100644 src/libcode/vx_grid/.find_grid_by_name.h.swp diff --git a/.github/workflows/testing.yml b/.github/workflows/testing.yml index 7a9a1f28dc..40c22d80e9 100644 --- a/.github/workflows/testing.yml +++ b/.github/workflows/testing.yml @@ -114,13 +114,13 @@ jobs: needs: [job_control] if: ${{ needs.job_control.outputs.run_unit_tests == 'true' }} steps: - - uses: dtcenter/metplus-action-data-update@v2 + - uses: dtcenter/metplus-action-data-update@v3 with: docker_name: ${{ secrets.DOCKER_USERNAME }} docker_pass: ${{ secrets.DOCKER_PASSWORD }} repo_name: ${{ github.repository }} data_prefix: unit_test - branch_name: ${{ needs.job_control.outputs.branch_name }} + branch_name: ${{ needs.job_control.outputs.truth_data_version }} docker_data_dir: /data/input/MET_test_data data_repo_dev: met-data-dev diff --git a/docs/Users_Guide/appendixB.rst b/docs/Users_Guide/appendixB.rst index a4d155a04f..c817e54a89 100644 --- a/docs/Users_Guide/appendixB.rst +++ b/docs/Users_Guide/appendixB.rst @@ -136,8 +136,6 @@ The NCEP verification regions that are implemented in MET as lat/lon polylines a * NAK.poly for Northern Alaska -* NAO.poly for Northern Atlantic Ocean - * NEC.poly for the Northern East Coast * NMT.poly for the Northern Mountain Region @@ -162,8 +160,6 @@ The NCEP verification regions that are implemented in MET as lat/lon polylines a * SPL.poly for the Southern Plains -* SPO.poly for the Southern Pacific Ocean - * SWC.poly for the Southern West Coast * SWD.poly for the Southwest Desert diff --git a/internal/scripts/installation/config/install_met_env.wcoss2_py3.10 b/internal/scripts/installation/config/install_met_env.wcoss2_py3.10 index ea9589e838..20244d34a1 100644 --- a/internal/scripts/installation/config/install_met_env.wcoss2_py3.10 +++ b/internal/scripts/installation/config/install_met_env.wcoss2_py3.10 @@ -2,7 +2,7 @@ module reset module use /apps/ops/para/libs/modulefiles/compiler/intel/19.1.3.304 export HPC_OPT=/apps/ops/para/libs module use /apps/dev/modulefiles/ -module load ve/evs/1.0 +module load ve/evs/2.0 module load netcdf/4.7.4 module load hdf5/1.10.6 module load bufr/11.6.0 @@ -12,13 +12,13 @@ module load libpng/1.6.37 module load gsl/2.7 module load g2c/1.6.4 -#export TEST_BASE=/apps/ops/para/libs/intel/19.1.3.304/met/11.1.0-rc1 +#export TEST_BASE=/apps/ops/para/libs/intel/19.1.3.304/met/11.1.0 export TEST_BASE=$(pwd) export LIB_DIR=${TEST_BASE}/external_libs export BIN_DIR_PATH=${TEST_BASE}/bin export COMPILER=intel_19.1.3.304 export MET_SUBDIR=${TEST_BASE} -export MET_TARBALL=v11.1.0-rc1.tar.gz +export MET_TARBALL=v11.1.0.tar.gz export USE_MODULES=TRUE export ADDTL_DIR=/apps/spack/gettext/0.21/intel/19.1.3.304/at2kdo4edvuhyzrt5g6zhwrdb7bdui4s/lib64 export PYTHON_MODULE=python_3.10.4 diff --git a/internal/test_unit/xml/unit_plot_data_plane.xml b/internal/test_unit/xml/unit_plot_data_plane.xml index e9e5ae965f..298b68c7b3 100644 --- a/internal/test_unit/xml/unit_plot_data_plane.xml +++ b/internal/test_unit/xml/unit_plot_data_plane.xml @@ -564,4 +564,18 @@ + + &MET_BIN;/plot_data_plane + \ + &DATA_DIR_MODEL;/nccf/percentile_extract_20230729T1200Z-B20230725T0030Z-visibility_at_screen_level.nc \ + &OUTPUT_DIR;/plot_data_plane/visibility_in_air_by_percentile.ps \ + 'name="visibility_in_air"; level="(6,*,*)";' \ + -title "Visibility in air" \ + -v 1 + + + &OUTPUT_DIR;/plot_data_plane/visibility_in_air_by_percentile.ps + + + diff --git a/src/basic/vx_math/ptile.cc b/src/basic/vx_math/ptile.cc index 6bf84ce5e0..9812403a84 100644 --- a/src/basic/vx_math/ptile.cc +++ b/src/basic/vx_math/ptile.cc @@ -23,6 +23,7 @@ using namespace std; #include "is_bad_data.h" #include "nint.h" +#include "vx_log.h" /////////////////////////////////////////////////////////////////////////////// @@ -63,10 +64,31 @@ int index; double delta; double p = bad_data_double; +// Range check +if ( t < 0.0 || t > 1.0 ) { + + mlog << Error << "\npercentile() -> " + << "requested percentile value (" << t + << ") must be between 0 and 1!\n\n"; + + exit ( 1 ); + +} + if ( n > 0 ) { + index = nint(floor((n - 1)*t)); - delta = (n-1)*t - index; - p = (1 - delta)*ordered_array[index] + delta*ordered_array[index+1]; + + // Use the last value + if ( index == (n - 1) ) { + p = ordered_array[index]; + } + // Interpolate linearly between two values + else if ( index >= 0 && index < (n - 1) ) { + delta = (n - 1)*t - index; + p = (1 - delta)*ordered_array[index] + delta*ordered_array[index + 1]; + } + } return ( p ); @@ -101,13 +123,30 @@ int index; float delta; float p = bad_data_float; +// Range check +if ( t < 0.0 || t > 1.0 ) { + + mlog << Error << "\npercentile_f() -> " + << "requested percentile value (" << t + << ") must be between 0 and 1!\n\n"; + + exit ( 1 ); + +} + if ( n > 0 ) { index = nint(floor((n - 1)*t)); - delta = (n - 1)*t - index; - - p = (1 - delta)*(ordered_array[index]) + delta*(ordered_array[index + 1]); + // Use the last value + if ( index == (n - 1) ) { + p = ordered_array[index]; + } + // Interpolate linearly between two values + else if ( index >= 0 && index < (n - 1) ) { + delta = (n - 1)*t - index; + p = (1 - delta)*ordered_array[index] + delta*ordered_array[index + 1]; + } } diff --git a/src/libcode/vx_data2d_nccf/data2d_nccf.cc b/src/libcode/vx_data2d_nccf/data2d_nccf.cc index f8b251c6d1..d0fcb98dcf 100644 --- a/src/libcode/vx_data2d_nccf/data2d_nccf.cc +++ b/src/libcode/vx_data2d_nccf/data2d_nccf.cc @@ -227,15 +227,19 @@ bool MetNcCFDataFile::data_plane(VarInfo &vinfo, DataPlane &plane) } else { long z_cnt = (long)_file->vlevels.n(); - if (z_cnt > 0) { - - zdim_slot = idx; + // Checks if the data veriable has a vertical dimension + if (0 <= data_var->z_slot) { org_z_offset = dim_offset; long z_offset = dim_offset; string z_dim_name; + + zdim_slot = idx; if (0 <= data_var->z_slot) { NcDim z_dim = get_nc_dim(data_var->var, data_var->z_slot); - if (IS_VALID_NC(z_dim)) z_dim_name = GET_NC_NAME(z_dim); + if (IS_VALID_NC(z_dim)) { + z_dim_name = GET_NC_NAME(z_dim); + z_cnt = get_dim_size(&z_dim); // override the virtical level count + } } if (!is_offset[idx]) { // convert the value to index for slicing @@ -663,12 +667,11 @@ long MetNcCFDataFile::convert_value_to_offset(double z_value, string z_dim_name) } } - if (!found && 0 < z_dim_name.length()) { - NcVarInfo *var_info = find_var_info_by_dim_name(_file->Var, z_dim_name, _file->Nvars); - if (var_info) { - long new_offset = get_index_at_nc_data(var_info->var, z_value, z_dim_name); - if (new_offset != bad_data_int) z_offset = new_offset; - } + // Overrides if the variable specific vertical dimension exists + NcVarInfo *var_info = find_var_info_by_dim_name(_file->Var, z_dim_name, _file->Nvars); + if (var_info) { + long new_offset = get_index_at_nc_data(var_info->var, z_value, z_dim_name); + z_offset = new_offset; } return z_offset; diff --git a/src/libcode/vx_data2d_nccf/nccf_file.cc b/src/libcode/vx_data2d_nccf/nccf_file.cc index 9c562bb74f..7ac0c9fdf0 100644 --- a/src/libcode/vx_data2d_nccf/nccf_file.cc +++ b/src/libcode/vx_data2d_nccf/nccf_file.cc @@ -257,9 +257,9 @@ bool NcCfFile::open(const char * filepath) else if( "latitude" == att_value ) _latVar = Var[j].var; else if( "longitude" == att_value ) _lonVar = Var[j].var; else if( ("air_pressure" == att_value || "height" == att_value) - && (0 == z_var) ) z_var = Var[j].var; + && (nullptr==z_var && 1==get_dim_count(Var[j].var))) z_var = Var[j].var; } - if ( Var[j].name == "time" && (valid_time_var == 0)) { + if ( Var[j].name == "time" && (valid_time_var == nullptr)) { valid_time_var = Var[j].var; _time_var_info = &Var[j]; } @@ -490,6 +490,13 @@ bool NcCfFile::open(const char * filepath) if (info) z_var = info->var; } + mlog << Debug(5) << method_name << "coordinate variables:" + << " x=" << (IS_VALID_NC_P(_xCoordVar) ? GET_NC_NAME_P(_xCoordVar) : "N/A") + << ", y=" << (IS_VALID_NC_P(_yCoordVar) ? GET_NC_NAME_P(_yCoordVar) : "N/A") + << ", z=" << (IS_VALID_NC_P(z_var) ? GET_NC_NAME_P(z_var) : "N/A") + << ", t=" << (IS_VALID_NC_P(valid_time_var) ? GET_NC_NAME_P(valid_time_var) : "N/A") + << "\n"; + // Pull out the vertical levels if (IS_VALID_NC_P(z_var)) { diff --git a/src/libcode/vx_grid/.find_grid_by_name.h.swp b/src/libcode/vx_grid/.find_grid_by_name.h.swp deleted file mode 100644 index 92793bd4ea02ff9ebab123f5373bd41e5d87b1da..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 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 Y`KP9dUBOLGHrm-GS#tx_JmhoxfAo$4t^fc4