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..af1c78f6f2 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". 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..90fae2a93a 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); + +} // // 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_python/.python_dataplane.cc.swp b/src/libcode/vx_data2d_python/.python_dataplane.cc.swp new file mode 100644 index 0000000000..bfc33dd3d5 Binary files /dev/null and b/src/libcode/vx_data2d_python/.python_dataplane.cc.swp differ 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())