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/data/table_files/ndbc_stations.xml b/data/table_files/ndbc_stations.xml index 7e73ef73a3..c536e399f4 100644 --- a/data/table_files/ndbc_stations.xml +++ b/data/table_files/ndbc_stations.xml @@ -260,6 +260,7 @@ + @@ -475,6 +476,7 @@ + @@ -777,6 +779,7 @@ + @@ -789,6 +792,7 @@ + @@ -919,9 +923,11 @@ + + @@ -946,6 +952,7 @@ + @@ -1113,11 +1120,13 @@ + + @@ -1231,6 +1240,7 @@ + @@ -1333,6 +1343,7 @@ + @@ -1341,6 +1352,7 @@ + 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..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/ascii2nc/ndbc_handler.cc b/src/tools/other/ascii2nc/ndbc_handler.cc index f76df3c4d8..cd9f960f90 100644 --- a/src/tools/other/ascii2nc/ndbc_handler.cc +++ b/src/tools/other/ascii2nc/ndbc_handler.cc @@ -87,11 +87,11 @@ NdbcHandler::NdbcHandler(const string &program_name) : // read in and parse the locations file if (!locations.initialize(locationsFileName)) { - mlog << Error << "\ncould not initialize station loations file\n\n"; + mlog << Error << "\nCannot initialize NDBC station loations file: " + << locationsFileName << "\n\n"; exit(1); } - //locations.print(); - + // // store column info for all the data columns (column names) // NOTE these will be used as index values in the observations @@ -215,13 +215,14 @@ bool NdbcHandler::_readObservations(LineDataFile &ascii_file) //////////////////////////////////////////////////////////////////////// bool NdbcHandler::_parseObservationLineStandard(DataLine &data_line, - const string &filename) + const string &filename) { string method_name = "NdbcHandler::_parseObservationLineStandard() "; if (format_version != NDBC_FORMAT_VERSION_STANDARD) { - mlog << Error << "\n" << method_name << "->" - << "Standard NDBC format is the only supported format\n\n"; + mlog << Warning << "\n" << method_name << "->" + << "Standard NDBC format is the only supported format: " + << filename << "\n\n"; return false; } @@ -229,11 +230,11 @@ bool NdbcHandler::_parseObservationLineStandard(DataLine &data_line, // Make sure that the line contains the correct number of tokens // if (data_line.n_items() != NUM_COLS_STANDARD) { - mlog << Error << "\n" << method_name << "-> " - << "line number " << data_line.line_number() - << " does not have the correct number of columns " << data_line.n_items() - << " (" << NUM_COLS_STANDARD << "). Skipping this line in \"" - << filename << "\".\n\n"; + mlog << Warning << "\n" << method_name << "-> " + << "Skipping line number " << data_line.line_number() + << " with an unexpected number of columns (" + << data_line.n_items() << " != " << NUM_COLS_STANDARD << "): " + << filename << "\n\n"; return false; } @@ -242,10 +243,10 @@ bool NdbcHandler::_parseObservationLineStandard(DataLine &data_line, // time_t valid_time = _getValidTime(data_line); if (valid_time == 0) { - mlog << Error << "\n" << method_name << "-> " - << "line number " << data_line.line_number() - << " time could not be parsed, skipping this line in \"" - << filename << "\".\n\n"; + mlog << Warning << "\n" << method_name << "-> " + << "Skipping line number " << data_line.line_number() + << " whose vaild time cannot not be parsed: " + << filename << "\n\n"; return false; } @@ -263,9 +264,9 @@ bool NdbcHandler::_parseObservationLineStandard(DataLine &data_line, name = column[i].name; grib_code = i; // it's not actually grib code, its obs_vid, according to howard _addObservations(Observation(header_type, stationId, valid_time, - stationLat, stationLon, stationAlt, - quality_flag, grib_code, pressure_level_hpa, - height_m, value, name)); + stationLat, stationLon, stationAlt, + quality_flag, grib_code, pressure_level_hpa, + height_m, value, name)); } return true; } @@ -287,15 +288,15 @@ bool NdbcHandler::_setStationInfo(const string &filename) // expect .txt as the name i0 = fname.find(".txt"); if (i0 == string::npos) { - mlog << Error << "\n" << "expect file name of format '.txt'\n" - << "Got " << fname << "\n\n"; + mlog << Warning << "\n" << "NDBC file name does not follow the " + << "expected '.txt' format: " << fname << "\n\n"; return false; } stationId = fname.substr(0, i0); if (!locations.lookupLatLonElev(stationId, stationLat, stationLon, - stationAlt)) { - mlog << Error << "\n" << "No location information found for station " - << stationId << " do not process file " << filename << "\n\n"; + stationAlt)) { + mlog << Warning << "\n" << "NDBC station " << stationId + << " location information not found: " << filename << "\n\n"; return false; } return true; @@ -323,8 +324,8 @@ bool NdbcHandler::_determineFileType(LineDataFile &ascii_file) } } format_version = NDBC_FORMAT_VERSION_UNKNOWN; - mlog << Error << "\nNdbcHandler::_determineFileType -> " - << "Unknown file type\n\n"; + mlog << Warning << "\nNdbcHandler::_determineFileType -> " + << "Unknown file type: " << ascii_file.filename() << "\n\n"; return false; } @@ -335,10 +336,10 @@ time_t NdbcHandler::_getValidTime(const DataLine &data_line) const // // Pull out the date information // - if (column_pointer_year < 0 || column_pointer_month < 0 || column_pointer_day < 0 || + if (column_pointer_year < 0 || column_pointer_month < 0 || column_pointer_day < 0 || column_pointer_hour < 0 || column_pointer_minute < 0) { - mlog << Error << "\nNdbcHandler::_getValidTime -> " - << "Not all time related column pointers are set\n\n"; + mlog << Warning << "\nNdbcHandler::_getValidTime -> " + << "Not all time related column pointers are set.\n\n"; return 0; } string year = _extractColumn(data_line, column_pointer_year); @@ -391,9 +392,9 @@ bool NdbcHandler::_readHeaderInfo(LineDataFile &ascii_file) // The first line of the file contains the headers // if (!(ascii_file >> data_line)) { - mlog << Error << "\nNdbcHandler::_readHeaderInfo() -> " - << "error reading header line from input ASCII file \"" - << ascii_file.filename() << "\"\n\n"; + mlog << Warning << "\nNdbcHandler::_readHeaderInfo() -> " + << "Problem reading header line from input ASCII file: " + << ascii_file.filename() << "\n\n"; return false; } @@ -401,9 +402,10 @@ bool NdbcHandler::_readHeaderInfo(LineDataFile &ascii_file) // Check for the correct number of columns in the header line // if (data_line.n_items() != NUM_COLS_STANDARD) { - mlog << Error << "\nNdbcHandler::_readHeaderInfo() -> " - << "NDBC file has incorrect number of columns (" - << data_line.n_items() << ") in header line\n\n"; + mlog << Warning << "\nNdbcHandler::_readHeaderInfo() -> " + << "Unexpected number of header columns (" << data_line.n_items() + << " != " << NUM_COLS_STANDARD << "): " + << ascii_file.filename() << "\n\n"; return false; } @@ -426,30 +428,33 @@ bool NdbcHandler::_readHeaderInfo(LineDataFile &ascii_file) } else { bool found = false; for (size_t j=0; j " - << "NDBC file has unknown header item " << s << "\n\n"; - status = false; + mlog << Warning << "\nNdbcHandler::_readHeaderInfo() -> " + << "Unexpected header column (" << s << "): " + << ascii_file.filename() << "\n\n"; + status = false; } } } - if (column_pointer_year == -1 || column_pointer_month == -1 || - column_pointer_day == -1 || column_pointer_hour == -1 || + if (column_pointer_year == -1 || column_pointer_month == -1 || + column_pointer_day == -1 || column_pointer_hour == -1 || column_pointer_minute == -1) { - mlog << Error << "\nNdbcHandler::_readHeaderInfo() -> " - << "NDBC file did not have all time fields in header \n\n"; - status = false; + mlog << Warning << "\nNdbcHandler::_readHeaderInfo() -> " + << "NDBC file did not have all time fields in header: " + << ascii_file.filename() << "\n\n"; + status = false; } for (size_t j=0; j " - << "NDBC file did not have all expected fields in header \n\n"; + mlog << Warning << "\nNdbcHandler::_readHeaderInfo() -> " + << "NDBC file did not have all expected fields in header: " + << ascii_file.filename() << "\n\n"; status = false; break; } 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