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 5cc2432fd6..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 diff --git a/internal/test_unit/config/GridStatConfig_climo_wrap_year b/internal/test_unit/config/GridStatConfig_climo_wrap_year new file mode 100644 index 0000000000..38e8ffcd0c --- /dev/null +++ b/internal/test_unit/config/GridStatConfig_climo_wrap_year @@ -0,0 +1,266 @@ +//////////////////////////////////////////////////////////////////////////////// +// +// Grid-Stat configuration file. +// +// For additional information, please see the MET User's Guide. +// +//////////////////////////////////////////////////////////////////////////////// + +// +// Output model name to be written +// +model = "GFSANL"; + +// +// Output description to be written +// May be set separately in each "obs.field" entry +// +desc = "NA"; + +// +// Output observation type to be written +// +obtype = "GFSANL"; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Verification grid +// +regrid = { + to_grid = NONE; + method = NEAREST; + width = 1; + vld_thresh = 0.5; + shape = SQUARE; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// May be set separately in each "field" entry +// +censor_thresh = []; +censor_val = []; +mpr_column = []; +mpr_thresh = []; +cat_thresh = []; +cnt_thresh = [ NA ]; +cnt_logic = UNION; +wind_thresh = [ NA ]; +wind_logic = UNION; +eclv_points = 0.05; +nc_pairs_var_name = ""; +nc_pairs_var_suffix = ""; +hss_ec_value = NA; +rank_corr_flag = FALSE; + +// +// Forecast and observation fields to be verified +// +fcst = { + + name = "TMP"; + level = "P500"; + + field = [ + { set_attr_init = "20201225_12"; set_attr_valid = "20201225_12"; nc_pairs_var_suffix = "20201225_12"; }, + { set_attr_init = "20210105_12"; set_attr_valid = "20210105_12"; nc_pairs_var_suffix = "20210105_12"; }, + { set_attr_init = "20201225_03"; set_attr_valid = "20201225_03"; nc_pairs_var_suffix = "20201225_03"; }, + { set_attr_init = "20201225_21"; set_attr_valid = "20201225_21"; nc_pairs_var_suffix = "20201225_21"; } + ]; +} +obs = fcst; + +//////////////////////////////////////////////////////////////////////////////// + +// +// Climatology data +// +climo_mean = { + + field = [ + { name = "TMP"; level = "P500"; }, + { name = "TMP"; level = "P500"; }, + { name = "TMP"; level = "P500"; }, + { name = "TMP"; level = "P500"; } + ]; + + file_name = [ ${CLIMO_MEAN_FILE_LIST} ]; + + regrid = { + method = BILIN; + width = 2; + vld_thresh = 0.5; + } + + time_interp_method = DW_MEAN; + day_interval = ${DAY_INTERVAL}; + hour_interval = ${HOUR_INTERVAL}; +} + +climo_stdev = climo_mean; +climo_stdev = { + file_name = [ ${CLIMO_STDEV_FILE_LIST} ]; +} + +// +// May be set separately in each "obs.field" entry +// +climo_cdf = { + cdf_bins = 1; + center_bins = TRUE; + write_bins = FALSE; + direct_prob = FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Verification masking regions +// +mask = { + grid = [ "FULL" ]; + poly = []; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Confidence interval settings +// +ci_alpha = [ 0.05 ]; + +boot = { + interval = PCTILE; + rep_prop = 1.0; + n_rep = 0; + rng = "mt19937"; + seed = ""; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Data smoothing methods +// +interp = { + field = BOTH; + vld_thresh = 1.0; + shape = SQUARE; + + type = [ + { + method = NEAREST; + width = 1; + } + ]; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Neighborhood methods +// +nbrhd = { + width = [ 1 ]; + cov_thresh = [ >=0.5 ]; + vld_thresh = 1.0; + shape = SQUARE; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Fourier decomposition +// +fourier = { + wave_1d_beg = []; + wave_1d_end = []; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Gradient statistics +// May be set separately in each "obs.field" entry +// +gradient = { + dx = [ 1, 2, 5 ]; + dy = [ 1, 3, 5 ]; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Distance Map statistics +// May be set separately in each "obs.field" entry +// +distance_map = { + baddeley_p = 2; + baddeley_max_dist = NA; + fom_alpha = 0.1; + zhu_weight = 0.5; + beta_value(n) = n * n / 2.0; +} + +//////////////////////////////////////////////////////////////////////////////// + +// +// Statistical output types +// +output_flag = { + fho = NONE; + ctc = NONE; + cts = NONE; + mctc = NONE; + mcts = NONE; + cnt = NONE; + sl1l2 = NONE; + sal1l2 = STAT; + vl1l2 = NONE; + val1l2 = NONE; + vcnt = NONE; + pct = NONE; + pstd = NONE; + pjc = NONE; + prc = NONE; + eclv = NONE; + nbrctc = NONE; + nbrcts = NONE; + nbrcnt = NONE; + grad = NONE; + dmap = NONE; + seeps = NONE; +} + +// +// NetCDF matched pairs output file +// +nc_pairs_flag = { + latlon = TRUE; + raw = FALSE; + diff = FALSE; + climo = TRUE; + climo_cdp = FALSE; + weight = FALSE; + nbrhd = FALSE; + fourier = FALSE; + gradient = FALSE; + distance_map = FALSE; + apply_mask = FALSE; +} + +//////////////////////////////////////////////////////////////////////////////// +// Threshold for SEEPS p1 (Probability of being dry) + +seeps_p1_thresh = NA; + +//////////////////////////////////////////////////////////////////////////////// + +grid_weight_flag = NONE; +tmp_dir = "/tmp"; +output_prefix = "${OUTPUT_PREFIX}"; +version = "V11.0.0"; + +//////////////////////////////////////////////////////////////////////////////// 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 7c8c0b300a..b513d5577d 100644 --- a/internal/test_unit/xml/unit_climatology_2.5deg.xml +++ b/internal/test_unit/xml/unit_climatology_2.5deg.xml @@ -50,4 +50,64 @@ + + + + &MET_BIN;/grid_stat + + OUTPUT_PREFIX WRAP_YEAR_CLIMO_2.5DEG + DAY_INTERVAL 31 + HOUR_INTERVAL 6 + CLIMO_MEAN_FILE_LIST + "&DATA_DIR_CLIMO;/NCEP_2.5deg/pgba_mean.19591215", + "&DATA_DIR_CLIMO;/NCEP_2.5deg/pgba_mean.19590115" + + + CLIMO_STDEV_FILE_LIST + "&DATA_DIR_CLIMO;/NCEP_2.5deg/pgba_stdv.19591215", + "&DATA_DIR_CLIMO;/NCEP_2.5deg/pgba_stdv.19590115" + + + + \ + &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_WRAP_YEAR_CLIMO_2.5DEG_000000L_20201225_120000V.stat + &OUTPUT_DIR;/climatology_2.5deg/grid_stat_WRAP_YEAR_CLIMO_2.5DEG_000000L_20201225_120000V_pairs.nc + + + + + + + &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_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_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())