diff --git a/.github/jobs/build_docker_image.sh b/.github/jobs/build_docker_image.sh index 4fabd88d2e..55bd37c644 100755 --- a/.github/jobs/build_docker_image.sh +++ b/.github/jobs/build_docker_image.sh @@ -15,8 +15,5 @@ time_command docker build -t ${DOCKERHUB_TAG} \ -f $DOCKERFILE_PATH ${GITHUB_WORKSPACE} if [ $? != 0 ]; then cat ${GITHUB_WORKSPACE}/docker_build.log - # Append the full make_install.log file - echo "Appending make_install.log to docker_build.log. See the logs artifact for details." - cat ${GITHUB_WORKSPACE}/make_install.log >> ${GITHUB_WORKSPACE}/docker_build.log exit 1 fi diff --git a/.github/jobs/set_job_controls.sh b/.github/jobs/set_job_controls.sh index e897aaa912..76a123d18b 100755 --- a/.github/jobs/set_job_controls.sh +++ b/.github/jobs/set_job_controls.sh @@ -6,7 +6,7 @@ run_unit_tests=false run_diff=false run_update_truth=false met_base_repo=met-base -met_base_tag=v1.1 +met_base_tag=v2.0_debian10 input_data_version=develop truth_data_version=develop diff --git a/.github/jobs/test_env_vars.sh b/.github/jobs/test_env_vars.sh index 4607e58f07..a77a9ca0f8 100755 --- a/.github/jobs/test_env_vars.sh +++ b/.github/jobs/test_env_vars.sh @@ -10,4 +10,4 @@ export MET_TEST_TRUTH=/data/output/met_test_truth export MET_TEST_DIFF=/data/output/met_test_diff export MET_TEST_RSCRIPT=/usr/bin/Rscript -export MET_TEST_MET_PYTHON_EXE=/usr/bin/python3 +export MET_TEST_MET_PYTHON_EXE=/usr/local/bin/python3 diff --git a/.github/workflows/build_docker_and_trigger_metplus.yml b/.github/workflows/build_docker_and_trigger_metplus.yml index 15cd652caf..89e5e14f67 100644 --- a/.github/workflows/build_docker_and_trigger_metplus.yml +++ b/.github/workflows/build_docker_and_trigger_metplus.yml @@ -29,7 +29,7 @@ jobs: env: SOURCE_BRANCH: ${{ steps.get_branch_name.outputs.branch_name }}-lite MET_BASE_REPO: met-base - MET_BASE_TAG: v1.1 + MET_BASE_TAG: v2.0_debian10 - name: Push Docker Image run: .github/jobs/push_docker_image.sh diff --git a/data/config/GridStatConfig_default b/data/config/GridStatConfig_default index 9ac3423238..3ac1b1050c 100644 --- a/data/config/GridStatConfig_default +++ b/data/config/GridStatConfig_default @@ -90,7 +90,6 @@ climo_mean = { } time_interp_method = DW_MEAN; - match_month = TRUE; day_interval = 31; hour_interval = 6; } diff --git a/docs/Users_Guide/config_options.rst b/docs/Users_Guide/config_options.rst index 66c2926af0..025c633d29 100644 --- a/docs/Users_Guide/config_options.rst +++ b/docs/Users_Guide/config_options.rst @@ -693,14 +693,16 @@ using the following entries: smoothing. The default is 120. Ignored if not Gaussian method. * The "gaussian_dx" and "gaussian_radius" settings must be in the same - units, such as kilometers or degress. Their ratio + units, such as kilometers or degress. Their ratio (sigma = gaussian_radius / gaussian_dx) determines the Guassian weighting function. * The "convert", "censor_thresh", and "censor_val" entries are described - below. When specified, these operations are applied to the output of the - regridding step. The conversion operation is applied first, followed by - the censoring operation. + below. When specified, these operations are applied to the output of the + regridding step. The conversion operation is applied first, followed by + the censoring operation. Note that these operations are limited in scope. + They are only applied if defined within the regrid dictionary itself. + Settings defined at higher levels of config file context are not applied. .. code-block:: none @@ -1318,9 +1320,8 @@ of several entires defining the climatology file names and fields to be used. * The "hour_interval" entry is an integer specifying the spacing in hours of the climatology data for each day. This should be set between 0 and 24, - with 6 and 12 being common choices. For example, use 6 for climatology data - with 4 times per day, such as 00Z, 06Z, 12Z, and 18Z. Use "NA" if the timing - of the climatology data should not be checked. + with 6 and 12 being common choices. Use "NA" if the timing of the + climatology data should not be checked. * The "day_interval" and "hour_interval" entries replace the deprecated entries "match_month", "match_day", and "time_step". @@ -1729,12 +1730,12 @@ This dictionary may include the following entries: * The "shape" entry may be set to SQUARE or CIRCLE to specify the shape of the smoothing area. -* The "type" entry is an array of dictionaries, each specifying an - interpolation method. Interpolation is performed over a N by N box - centered on each point, where N is the width specified. Each of these +* The "type" entry is an array of dictionaries, each specifying one or more + interpolation methods and widths. Interpolation is performed over an N by N + box centered on each point, where N is the width specified. Each of these dictionaries must include: - * The "width" entry is an integer which specifies the size of the + * The "width" entry is an array of integers to specify the size of the interpolation area. The area is either a square or circle containing the observation point. The width value specifies the width of the square or diameter of the circle. A width value of 1 is interpreted @@ -1747,7 +1748,7 @@ This dictionary may include the following entries: grid point closest to the observation point. For grid-to-grid comparisons (i.e. Grid-Stat), the width must be odd. - * The "method" entry specifies the interpolation procedure to be + * The "method" entry is an array of interpolation procedures to be applied to the points in the box: * MIN for the minimum value @@ -1792,6 +1793,9 @@ This dictionary may include the following entries: only valid smoothing methods are MIN, MAX, MEDIAN, UW_MEAN, and GAUSSIAN, and MAXGAUSS. + * If multiple "method" and "width" options are specified, all possible + permutations of their values are applied. + .. code-block:: none interp = { @@ -1801,8 +1805,8 @@ This dictionary may include the following entries: type = [ { - method = UW_MEAN; - width = 1; + method = [ NEAREST ]; + width = [ 1 ]; } ]; } diff --git a/internal/scripts/docker/build_met_docker.sh b/internal/scripts/docker/build_met_docker.sh index a7e2aa7a07..df02108390 100755 --- a/internal/scripts/docker/build_met_docker.sh +++ b/internal/scripts/docker/build_met_docker.sh @@ -2,33 +2,37 @@ echo "Running script to build MET in Docker" -LOG_FILE=/met/logs/MET-${MET_GIT_NAME}_configure.log - source internal/scripts/environment/development.docker +mkdir -p /met/logs + +LOG_FILE=/met/logs/MET-${MET_GIT_NAME}_configure.log echo "Configuring MET ${MET_GIT_NAME} and writing log file ${LOG_FILE}" ./bootstrap -./configure --enable-grib2 --enable-mode_graphics --enable-modis --enable-lidar2nc --enable-python > ${LOG_FILE} +./configure --enable-grib2 --enable-mode_graphics --enable-modis --enable-lidar2nc --enable-python CPPFLAGS="-I/usr/local/include -I/usr/local/include/freetype2 -I/usr/local/include/cairo" > ${LOG_FILE} 2>&1 if [ $? != 0 ]; then - exit 1 + cat ${LOG_FILE} + exit 1 fi if [ ! -z "${MAKE_ARGS}" ]; then echo Adding make arguments: ${MAKE_ARGS} fi -LOG_FILE=/met/MET-${MET_GIT_NAME}/make_install.log +LOG_FILE=/met/logs/MET-${MET_GIT_NAME}_make_install.log echo "Compiling MET ${MET_GIT_NAME} and writing log file ${LOG_FILE}" make ${MAKE_ARGS} install > ${LOG_FILE} if [ $? != 0 ]; then - exit 1 + cat ${LOG_FILE} + exit 1 fi LOG_FILE=/met/logs/MET-${MET_GIT_NAME}_make_test.log echo "Testing MET ${MET_GIT_NAME} and writing log file ${LOG_FILE}" make ${MAKE_ARGS} test > ${LOG_FILE} 2>&1 if [ $? != 0 ]; then - exit 1 + cat ${LOG_FILE} + exit 1 fi if [[ $MET_GIT_NAME == "v"* ]]; then diff --git a/internal/scripts/environment/development.docker b/internal/scripts/environment/development.docker index c7be4a77fe..e7968889f6 100644 --- a/internal/scripts/environment/development.docker +++ b/internal/scripts/environment/development.docker @@ -1,5 +1,4 @@ -# Define the development environment for NCAR project machine seneca -# Based on settings in /usr/local/src/met/README.snat +# Define the development environment for Docker # Top-level MET project directory MET_PROJ_DIR=`ls -1d /met/MET*` @@ -7,33 +6,17 @@ MET_PROJ_DIR=`ls -1d /met/MET*` # Variables required to build MET export MET_DEVELOPMENT=true -export MET_NETCDF=/usr/local -export MET_HDF5INC=/usr/include -export MET_HDF5LIB=/usr/lib64 -export MET_HDF=/usr/local/hdf -export MET_HDFEOS=/usr/local/hdfeos -export MET_BUFR=/usr/local -export MET_GRIB2CINC=/usr/include -export MET_GRIB2CLIB=/usr/lib64 -export MET_GSLINC=/usr/include/gsl -export MET_GSLLIB=/usr/lib64 -export MET_CAIROINC=/usr/include/cairo -export MET_CAIROLIB=/usr/lib64 -export MET_FREETYPEINC=/usr/include/freetype2 -export MET_FREETYPELIB=/usr/lib64 -export MET_JASPERLIB=/usr/lib64 - -export MET_PYTHON_BIN_EXE=/usr/bin/python3 -export MET_PYTHON_CC="-I/usr/include/python3.6m" -export MET_PYTHON_LD="-L/usr/lib64 -lpython3.6m -lpthread -ldl -lutil -lm" - -# -D__64BIT__ is required because we've compiled libgrib2c.a with that flag -export CFLAGS="-DUNDERSCORE -fPIC -D__64BIT__ -g" +export MET_PYTHON=/usr/local +export MET_PYTHON_BIN_EXE=${MET_PYTHON}/bin/python3 +export MET_PYTHON_CC="-I${MET_PYTHON}/include/python3.10" +export MET_PYTHON_LD="-L${MET_PYTHON}/lib -lpython3.10 -lcrypt -lpthread -ldl -lutil -lm" + +export CFLAGS="-DUNDERSCORE -fPIC -g" export CXXFLAGS=${CFLAGS} # Set LDFLAGS to include -rpath settings when compiling MET export LDFLAGS="-Wl,--disable-new-dtags" -export LDFLAGS="${LDFLAGS} -Wl,-rpath,/usr/local/lib:/usr/lib64:${MET_HDF}/lib:${MET_HDFEOS}/lib" +export LDFLAGS="${LDFLAGS} -Wl,-rpath,/usr/local/lib:/usr/lib64" # Variables required to run MET export MET_TEST_INPUT=${MET_PROJ_DIR}/MET_test_data/unit_test @@ -44,3 +27,16 @@ export MET_TEST_RSCRIPT=/usr/bin/Rscript # set make arguments to build using multiple jobs export MAKE_ARGS=-j + +export TEST_BASE=/met +export COMPILER=gnu +export MET_SUBDIR=${TEST_BASE} +export MET_TARBALL=none +export USE_MODULES=FALSE + +export MET_INSTALL_DIR=/usr/local + +export COMPILE_HDF=1 +export COMPILE_HDFEOS=1 +export COMPILE_FREETYPE=1 +export COMPILE_CAIRO=1 diff --git a/internal/scripts/installation/compile_MET_all.sh b/internal/scripts/installation/compile_MET_all.sh index e0ff3290cc..9810a124f2 100755 --- a/internal/scripts/installation/compile_MET_all.sh +++ b/internal/scripts/installation/compile_MET_all.sh @@ -89,8 +89,23 @@ echo "MET_TARBALL = ${MET_TARBALL? "ERROR: MET_TARBALL must be set"}" echo "USE_MODULES = ${USE_MODULES? "ERROR: USE_MODULES must be set to TRUE if using modules or FALSE otherwise"}" echo ${MAKE_ARGS:+MAKE_ARGS = $MAKE_ARGS} -export LIB_DIR=${TEST_BASE}/external_libs +LIB_DIR=${TEST_BASE}/external_libs MET_DIR=${MET_SUBDIR} + +if [ -z "${BIN_DIR_PATH}" ]; then + if [ -z "${MET_INSTALL_DIR}" ]; then + BIN_DIR_PATH=${TEST_BASE}/bin + else + BIN_DIR_PATH=${MET_INSTALL_DIR}/bin + fi +fi + +if [ -z "${MET_INSTALL_DIR}" ]; then + MET_INSTALL_DIR=${MET_DIR} +else + LIB_DIR=${MET_INSTALL_DIR} +fi + TAR_DIR=${TEST_BASE}/tar_files MET_TARBALL=${TAR_DIR}/${MET_TARBALL} @@ -415,12 +430,16 @@ if [ $COMPILE_G2CLIB -eq 1 ]; then rm -rf ${LIB_DIR}/g2clib/g2clib* tar -xf ${TAR_DIR}/g2clib*.tar -C ${LIB_DIR}/g2clib cd ${LIB_DIR}/g2clib/g2clib* - cat makefile | \ - sed -r 's/INC=.*/INC=-I${LIB_DIR}\/include -I${LIB_DIR}\/include\/jasper/g' | \ - sed 's/CC=gcc/CC=${CC_COMPILER}/g' | \ - sed 's/-D__64BIT__//g' \ - > makefile_new - mv makefile_new makefile + sed -i 's|INC=.*|INC=-I${LIB_DIR}/include -I${LIB_DIR}/include/jasper|g' makefile + + # allow other compilers besides gcc + sed -i 's/CC=gcc/CC=${CC_COMPILER}/g' makefile + + # remove -D__64BIT__ flag because compiling with it has + # shown issues with GRIB/GRIB2 files that are over 2GB in size + # This flag was removed in g2clib 1.6.4 + # so this can be removed if the version is updated + sed -i 's/-D__64BIT__//g' makefile export CC_COMPILER=${CC} echo "cd `pwd`" # g2clib appears to compile but causes failure compiling MET if -j argument is used @@ -628,7 +647,7 @@ if [[ $COMPILER_FAMILY == "pgi" ]]; then export OPT_ARGS="${OPT_ARGS} FFLAGS=-lpgf90" fi -configure_cmd="./configure --prefix=${MET_DIR} --bindir=${BIN_DIR_PATH}" +configure_cmd="./configure --prefix=${MET_INSTALL_DIR} --bindir=${BIN_DIR_PATH}" configure_cmd="${configure_cmd} BUFRLIB_NAME=${BUFRLIB_NAME}" configure_cmd="${configure_cmd} GRIB2CLIB_NAME=${GRIB2CLIB_NAME} --enable-grib2" if [[ ! -z ${MET_FREETYPEINC} && ! -z ${MET_FREETYPELIB} && \ diff --git a/internal/test_unit/config/PointStatConfig_climo b/internal/test_unit/config/PointStatConfig_climo index 565463ada5..7bcf6c318f 100644 --- a/internal/test_unit/config/PointStatConfig_climo +++ b/internal/test_unit/config/PointStatConfig_climo @@ -53,21 +53,24 @@ fcst = { field = [ { - name = "TMP"; - level = [ "Z2" ]; - desc = "KELVIN"; + name = "TMP"; + level = [ "Z2" ]; + desc = "KELVIN"; + set_attr_units = "K"; }, { - name = "TMP"; - level = [ "Z2" ]; - desc = "CELCIUS"; - convert(x) = K_to_C(x); + name = "TMP"; + level = [ "Z2" ]; + desc = "CELCIUS"; + convert(x) = K_to_C(x); + set_attr_units = "C"; }, { - name = "TMP"; - level = [ "Z2" ]; - desc = "FAHRENHEIT"; - convert(x) = K_to_F(x); + name = "TMP"; + level = [ "Z2" ]; + desc = "FAHRENHEIT"; + convert(x) = K_to_F(x); + set_attr_units = "F"; }, { name = "TMP"; diff --git a/internal/test_unit/xml/unit_climatology_2.5deg.xml b/internal/test_unit/xml/unit_climatology_2.5deg.xml index ed534d0191..b513d5577d 100644 --- a/internal/test_unit/xml/unit_climatology_2.5deg.xml +++ b/internal/test_unit/xml/unit_climatology_2.5deg.xml @@ -81,4 +81,33 @@ + + + + &MET_BIN;/grid_stat + + OUTPUT_PREFIX SINGLE_MONTH_CLIMO_2.5DEG + DAY_INTERVAL 31 + HOUR_INTERVAL 6 + CLIMO_MEAN_FILE_LIST + "&DATA_DIR_CLIMO;/NCEP_2.5deg/pgba_mean.19591215" + + + CLIMO_STDEV_FILE_LIST + "&DATA_DIR_CLIMO;/NCEP_2.5deg/pgba_stdv.19591215" + + + + \ + &DATA_DIR_MODEL;/grib2/gfsanl/gfsanl_4_20120409_1200_000.grb2 \ + &DATA_DIR_MODEL;/grib2/gfsanl/gfsanl_4_20120409_1200_000.grb2 \ + &CONFIG_DIR;/GridStatConfig_climo_wrap_year \ + -outdir &OUTPUT_DIR;/climatology_2.5deg -v 3 + + + &OUTPUT_DIR;/climatology_2.5deg/grid_stat_SINGLE_MONTH_CLIMO_2.5DEG_000000L_20201225_120000V.stat + &OUTPUT_DIR;/climatology_2.5deg/grid_stat_SINGLE_MONTH_CLIMO_2.5DEG_000000L_20201225_120000V_pairs.nc + + + diff --git a/scripts/config/GridStatConfig_all b/scripts/config/GridStatConfig_all index ae38f06cd5..3d0e53f12e 100644 --- a/scripts/config/GridStatConfig_all +++ b/scripts/config/GridStatConfig_all @@ -107,7 +107,6 @@ climo_mean = { } time_interp_method = DW_MEAN; - match_month = TRUE; match_day = FALSE; time_step = 21600; } diff --git a/src/basic/vx_cal/doyhms_to_unix.cc b/src/basic/vx_cal/doyhms_to_unix.cc index 2c130131bb..e864089d88 100644 --- a/src/basic/vx_cal/doyhms_to_unix.cc +++ b/src/basic/vx_cal/doyhms_to_unix.cc @@ -178,3 +178,4 @@ return ( dt ); //////////////////////////////////////////////////////////////////////// + diff --git a/src/basic/vx_config/config_util.cc b/src/basic/vx_config/config_util.cc index 52817f1b6d..318f974654 100644 --- a/src/basic/vx_config/config_util.cc +++ b/src/basic/vx_config/config_util.cc @@ -1299,14 +1299,18 @@ RegridInfo parse_conf_regrid(Dictionary *dict, bool error_out) { info.gaussian.trunc_factor = (is_bad_data(conf_value) ? default_trunc_factor : conf_value); if (info.method == InterpMthd_Gaussian || info.method == InterpMthd_MaxGauss) info.gaussian.compute(); + // MET#2437 Do not search the higher levels of config file context for convert, + // censor_thresh, and censor_val. They must be specified within the + // regrid dictionary itself. + // Conf: convert - info.convert_fx.set(regrid_dict->lookup(conf_key_convert)); + info.convert_fx.set(regrid_dict->lookup(conf_key_convert, false)); // Conf: censor_thresh - info.censor_thresh = regrid_dict->lookup_thresh_array(conf_key_censor_thresh, false); + info.censor_thresh = regrid_dict->lookup_thresh_array(conf_key_censor_thresh, false, true, false); // Conf: censor_val - info.censor_val = regrid_dict->lookup_num_array(conf_key_censor_val, false); + info.censor_val = regrid_dict->lookup_num_array(conf_key_censor_val, false, true, false); // Validate the settings info.validate(); diff --git a/src/basic/vx_config/dictionary.cc b/src/basic/vx_config/dictionary.cc index 08dc1f7fe9..9a738810f3 100644 --- a/src/basic/vx_config/dictionary.cc +++ b/src/basic/vx_config/dictionary.cc @@ -1261,7 +1261,7 @@ return ( e[n] ); //////////////////////////////////////////////////////////////////////// -const DictionaryEntry * Dictionary::lookup(const std::string name) +const DictionaryEntry * Dictionary::lookup(const std::string name, bool search_parent) { @@ -1288,13 +1288,13 @@ scope = Name.split("."); if ( scope.n_elements() == 1 ) { - return ( lookup_simple(name) ); + return ( lookup_simple(name, search_parent) ); } for (j=0; j<(scope.n_elements() - 1); ++j) { - E = D->lookup(scope[j].c_str()); + E = D->lookup(scope[j].c_str(), search_parent); if ( !E ) { @@ -1320,7 +1320,7 @@ for (j=0; j<(scope.n_elements() - 1); ++j) { const string stub = scope[scope.n_elements() - 1].c_str(); -E = D->lookup_simple(stub); +E = D->lookup_simple(stub, search_parent); if ( E ) { @@ -1335,7 +1335,11 @@ if ( E ) { E = (const DictionaryEntry *) 0; -if ( Parent ) E = Parent->lookup(name); +if ( search_parent ) { + + if ( Parent ) E = Parent->lookup(name, search_parent); + +} // // done @@ -1351,7 +1355,7 @@ return ( E ); //////////////////////////////////////////////////////////////////////// -const DictionaryEntry * Dictionary::lookup_simple(const std::string name) +const DictionaryEntry * Dictionary::lookup_simple(const std::string name, bool search_parent) { @@ -1381,8 +1385,11 @@ for (j=0; jlookup(name); +if ( search_parent ) { + if ( Parent ) E = Parent->lookup(name, search_parent); + +} // // done // @@ -1473,11 +1480,12 @@ return; bool Dictionary::lookup_bool(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; if ( Entry ) { @@ -1521,11 +1529,12 @@ return ( Entry->b_value() ); int Dictionary::lookup_int(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; if ( Entry ) { @@ -1569,11 +1578,12 @@ return ( Entry->i_value() ); double Dictionary::lookup_double(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; double v = bad_data_double; @@ -1641,11 +1651,12 @@ return ( v ); NumArray Dictionary::lookup_num_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); const Dictionary * Dict = (const Dictionary *) 0; ConfigObjectType Type = no_config_object_type; bool is_correct_type = false; @@ -1765,12 +1776,13 @@ return ( array ); IntArray Dictionary::lookup_int_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { IntArray array; -NumArray num_array = lookup_num_array(name, error_out, print_warning); +NumArray num_array = lookup_num_array(name, error_out, print_warning, search_parent); for (int i=0; istring_value() ); StringArray Dictionary::lookup_string_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); const Dictionary * Dict = (const Dictionary *) 0; bool is_correct_type = false; StringArray array; @@ -1934,11 +1948,12 @@ return ( array ); SingleThresh Dictionary::lookup_thresh(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; if ( Entry ) { @@ -1987,11 +2002,12 @@ return ( *(Entry->thresh_value()) ); ThreshArray Dictionary::lookup_thresh_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); const Dictionary * Dict = (const Dictionary *) 0; bool is_correct_type = false; ThreshArray array; @@ -2089,11 +2105,12 @@ return ( array ); Dictionary *Dictionary::lookup_dictionary(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; if ( Entry ) { @@ -2139,11 +2156,12 @@ return ( Entry->dict_value() ); Dictionary *Dictionary::lookup_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; if ( Entry ) { @@ -2191,18 +2209,19 @@ return ( Entry->array_value() ); int Dictionary::lookup_seconds(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -ConcatString cs = lookup_string(name, false); +ConcatString cs = lookup_string(name, false, true, search_parent); if ( LastLookupStatus ) { if ( cs.empty() ) return ( bad_data_int ); else return ( timestring_to_sec( cs.c_str() ) ); } -return ( lookup_int(name, error_out, print_warning) ); +return ( lookup_int(name, error_out, print_warning, search_parent) ); } @@ -2212,11 +2231,12 @@ return ( lookup_int(name, error_out, print_warning) ); IntArray Dictionary::lookup_seconds_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -StringArray sa = lookup_string_array(name, error_out, print_warning); +StringArray sa = lookup_string_array(name, error_out, print_warning, search_parent); IntArray ia; int j; @@ -2232,11 +2252,12 @@ return ( ia ); unixtime Dictionary::lookup_unixtime(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -ConcatString cs = lookup_string(name, error_out, print_warning); +ConcatString cs = lookup_string(name, error_out, print_warning, search_parent); if ( cs.empty() ) return ( (unixtime) 0 ); else return ( timestring_to_unix( cs.c_str() ) ); @@ -2248,11 +2269,12 @@ else return ( timestring_to_unix( cs.c_str() ) ); TimeArray Dictionary::lookup_unixtime_array(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -StringArray sa = lookup_string_array(name, error_out, print_warning); +StringArray sa = lookup_string_array(name, error_out, print_warning, search_parent); TimeArray ta; int j; @@ -2269,11 +2291,12 @@ return ( ta ); PiecewiseLinear *Dictionary::lookup_pwl(const char * name, bool error_out, - bool print_warning) + bool print_warning, + bool search_parent) { -const DictionaryEntry * Entry = lookup(name); +const DictionaryEntry * Entry = lookup(name, search_parent); bool is_correct_type = false; if ( Entry ) { diff --git a/src/basic/vx_config/dictionary.h b/src/basic/vx_config/dictionary.h index 4265b7c3d1..45ed66e946 100644 --- a/src/basic/vx_config/dictionary.h +++ b/src/basic/vx_config/dictionary.h @@ -179,6 +179,8 @@ static const bool default_dictionary_error_out = true; static const bool default_dictionary_print_warning = true; +static const bool default_dictionary_search_parent = true; + //////////////////////////////////////////////////////////////////////// @@ -195,7 +197,8 @@ class Dictionary { void patch_parents(); - virtual const DictionaryEntry * lookup_simple(const std::string name); // no scope + virtual const DictionaryEntry * lookup_simple(const std::string name, + bool search_parent = true); // no scope int Nentries; @@ -253,7 +256,7 @@ class Dictionary { virtual void store(const Dictionary &); - virtual const DictionaryEntry * lookup(const std::string name); + virtual const DictionaryEntry * lookup(const std::string name, bool search_parent = true); // // convenience functions @@ -261,43 +264,56 @@ class Dictionary { bool lookup_bool (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); int lookup_int (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); double lookup_double (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); NumArray lookup_num_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); IntArray lookup_int_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); ConcatString lookup_string (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); StringArray lookup_string_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); SingleThresh lookup_thresh (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); ThreshArray lookup_thresh_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); int lookup_seconds (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); IntArray lookup_seconds_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); unixtime lookup_unixtime (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); TimeArray lookup_unixtime_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); // // return value not allocated @@ -305,13 +321,16 @@ class Dictionary { Dictionary * lookup_dictionary (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); Dictionary * lookup_array (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); PiecewiseLinear * lookup_pwl (const char * name, bool error_out = default_dictionary_error_out, - bool print_warning = default_dictionary_print_warning); + bool print_warning = default_dictionary_print_warning, + bool search_parent = default_dictionary_search_parent); }; diff --git a/src/libcode/vx_data2d_grib/grib_utils.cc b/src/libcode/vx_data2d_grib/grib_utils.cc index c1ef70f775..71b3ee8dc2 100644 --- a/src/libcode/vx_data2d_grib/grib_utils.cc +++ b/src/libcode/vx_data2d_grib/grib_utils.cc @@ -572,6 +572,12 @@ data.nx = char2_to_int(gds.nx); // Number of points in the y-direction data.ny = char2_to_int(gds.ny); +data.eccentricity = 0.; +data.false_east = 0.; +data.false_north = 0.; +data.scale_factor = 1.0; +data.dy_km = data.d_km; + data.dump(); // diff --git a/src/libcode/vx_data2d_grib2/data2d_grib2.cc b/src/libcode/vx_data2d_grib2/data2d_grib2.cc index 42582b781e..45d931b9c2 100644 --- a/src/libcode/vx_data2d_grib2/data2d_grib2.cc +++ b/src/libcode/vx_data2d_grib2/data2d_grib2.cc @@ -1172,6 +1172,11 @@ void MetGrib2DataFile::read_grib2_grid( gribfield *gfld) { data.r_km = r_km; data.nx = gfld->igdtmpl[7]; data.ny = gfld->igdtmpl[8]; + data.eccentricity = 0.; + data.false_east = 0.; + data.false_north = 0.; + data.scale_factor = 1.0; + data.dy_km = data.d_km; // check for dx != dy if( !is_eq((double)gfld->igdtmpl[14] / 1000000.0, diff --git a/src/libcode/vx_data2d_nc_met/get_met_grid.cc b/src/libcode/vx_data2d_nc_met/get_met_grid.cc index 6016ab4dd2..67ddad0fa8 100644 --- a/src/libcode/vx_data2d_nc_met/get_met_grid.cc +++ b/src/libcode/vx_data2d_nc_met/get_met_grid.cc @@ -447,6 +447,12 @@ get_global_att(ncfile, string("nx"), data.nx); // Number of points in the y-direction get_global_att(ncfile, string("ny"), data.ny); +data.eccentricity = 0.; +data.false_east = 0.; +data.false_north = 0.; +data.scale_factor = 1.0; +data.dy_km = data.d_km; + data.dump(); // @@ -643,6 +649,12 @@ get_global_att(ncfile, string("nx"), data.nx); // Number of points in the y-direction get_global_att(ncfile, string("ny"), data.ny); +data.eccentricity = 0.; +data.false_east = 0.; +data.false_north = 0.; +data.scale_factor = 1.0; +data.dy_km = data.d_km; + data.dump(); // diff --git a/src/libcode/vx_data2d_nc_pinterp/get_pinterp_grid.cc b/src/libcode/vx_data2d_nc_pinterp/get_pinterp_grid.cc index b5a78b109a..d93f0d3701 100644 --- a/src/libcode/vx_data2d_nc_pinterp/get_pinterp_grid.cc +++ b/src/libcode/vx_data2d_nc_pinterp/get_pinterp_grid.cc @@ -185,6 +185,12 @@ data.d_km *= 0.001; data.r_km = default_grib_radius_km; +data.eccentricity = 0.; +data.false_east = 0.; +data.false_north = 0.; +data.scale_factor = 1.0; +data.dy_km = data.d_km; + // // done // diff --git a/src/libcode/vx_data2d_python/grid_from_python_dict.cc b/src/libcode/vx_data2d_python/grid_from_python_dict.cc index 8c9aa7dae1..93de48387d 100644 --- a/src/libcode/vx_data2d_python/grid_from_python_dict.cc +++ b/src/libcode/vx_data2d_python/grid_from_python_dict.cc @@ -208,6 +208,11 @@ data.r_km = dict.lookup_double("r_km"); data.nx = dict.lookup_int("nx"); data.ny = dict.lookup_int("ny"); +data.eccentricity = 0.; +data.false_east = 0.; +data.false_north = 0.; +data.scale_factor = 1.0; +data.dy_km = data.d_km; //////////////// diff --git a/src/libcode/vx_statistics/read_climo.cc b/src/libcode/vx_statistics/read_climo.cc index 142833337f..47666cafe3 100644 --- a/src/libcode/vx_statistics/read_climo.cc +++ b/src/libcode/vx_statistics/read_climo.cc @@ -299,6 +299,26 @@ DataPlaneArray climo_time_interp(const DataPlaneArray &dpa, int day_ts, } // For exactly 2 fields, do a simple time interpolation. else if(it->second.n() == 2) { + + // If the valid time falls outside the climo times, shift them. + if(vld_ut < min(dpa[it->second[0]].valid(), dpa[it->second[1]].valid()) || + vld_ut > max(dpa[it->second[0]].valid(), dpa[it->second[1]].valid())) { + + unixtime ut1 = dpa[it->second[0]].valid(); + unixtime ut2 = dpa[it->second[1]].valid(); + + int shift_sec = day_of_year_diff(min(ut1, ut2), vld_ut) * sec_per_day; + + mlog << Debug(3) + << "Shifting climatology times " << shift_sec / sec_per_day + << " day(s) from " << unix_to_yyyymmdd_hhmmss(ut1) + << " to " << unix_to_yyyymmdd_hhmmss(ut1 + shift_sec) + << " and " << unix_to_yyyymmdd_hhmmss(ut2) + << " to " << unix_to_yyyymmdd_hhmmss(ut2 + shift_sec) << ".\n"; + dpa[it->second[0]].set_valid(ut1 + shift_sec); + dpa[it->second[1]].set_valid(ut2 + shift_sec); + } + mlog << Debug(3) << "Interpolating climatology fields at " << unix_to_yyyymmdd_hhmmss(dpa[it->second[0]].valid()) diff --git a/src/tools/other/mode_time_domain/nc_grid.cc b/src/tools/other/mode_time_domain/nc_grid.cc index e31246ab4d..022a2e8ebe 100644 --- a/src/tools/other/mode_time_domain/nc_grid.cc +++ b/src/tools/other/mode_time_domain/nc_grid.cc @@ -191,6 +191,11 @@ data.r_km = string_att_as_double(f, "r_km"); data.nx = string_att_as_int(f, "nx"); data.ny = string_att_as_int(f, "ny"); +data.eccentricity = 0.; +data.false_east = 0.; +data.false_north = 0.; +data.scale_factor = 1.0; +data.dy_km = data.d_km; // // done