From 029084e200a6a09379da75cea915ac5b246b7930 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Thu, 8 Sep 2022 13:51:05 -0600 Subject: [PATCH 01/23] Per #1908, removing nbrhd_prob, nmep_smooth, and several ensemble_flag options. --- data/config/EnsembleStatConfig_default | 35 --- src/tools/core/ensemble_stat/ensemble_stat.cc | 223 +----------------- src/tools/core/ensemble_stat/ensemble_stat.h | 2 - .../ensemble_stat/ensemble_stat_conf_info.cc | 91 +------ .../ensemble_stat/ensemble_stat_conf_info.h | 17 -- 5 files changed, 5 insertions(+), 363 deletions(-) diff --git a/data/config/EnsembleStatConfig_default b/data/config/EnsembleStatConfig_default index 93380170ef..ddea4f8743 100644 --- a/data/config/EnsembleStatConfig_default +++ b/data/config/EnsembleStatConfig_default @@ -70,33 +70,6 @@ control_id = ""; //////////////////////////////////////////////////////////////////////////////// -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // @@ -287,15 +260,7 @@ ensemble_flag = { latlon = TRUE; mean = TRUE; stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; rank = TRUE; weight = FALSE; } diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index f710378cef..1b3250f400 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -66,7 +66,8 @@ // 034 01/14/21 McCabe MET #1695 All members in one file. // 035 02/15/22 Halley Gotway MET #1583 Add HiRA option. // 036 02/20/22 Halley Gotway MET #1259 Write probabilistic statistics. -// 037 07/06/22 Howard Soh METplus-Internal #19 Rename main to met_main +// 037 07/06/22 Howard Soh METplus-Internal #19 Rename main to met_main. +// 038 09/06/22 Halley Gotway MET #1908 Remove ensemble processing logic. // //////////////////////////////////////////////////////////////////////// @@ -412,14 +413,6 @@ void process_command_line(int argc, char **argv) { // Set the model name shc.set_model(conf_info.model.c_str()); - // Allocate arrays to store threshold counts - thresh_cnt_na = new NumArray [conf_info.get_max_n_ens_thresh()]; - thresh_nbrhd_cnt_na = new NumArray * [conf_info.get_max_n_ens_thresh()]; - - for(i=0; i 0 - if(conf_info.nc_info.do_nmep) { - DataPlane frac_dp; - - // Loop over thresholds - for(i=0; i 0) thresh_nbrhd_cnt_na[i][j].inc(k, 1); - } // end for k - - } // end for j - } // end for i - } // end if do_nmep - return; } @@ -2807,16 +2762,10 @@ void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { int i, j, k, l; double t, v; char type_str[max_str_len]; - DataPlane prob_dp, nbrhd_dp; // Allocate memory for storing ensemble data float * ens_mean = new float [nxy]; float * ens_stdev = new float [nxy]; - float * ens_minus = new float [nxy]; - float * ens_plus = new float [nxy]; - float * ens_min = new float [nxy]; - float * ens_max = new float [nxy]; - float * ens_range = new float [nxy]; int * ens_vld = new int [nxy]; // Store the threshold for the ratio of valid data points @@ -2832,11 +2781,6 @@ void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { if((double) (cnt_na[i]/n_ens_vld[i_var]) < t) { ens_mean[i] = bad_data_float; ens_stdev[i] = bad_data_float; - ens_minus[i] = bad_data_float; - ens_plus[i] = bad_data_float; - ens_min[i] = bad_data_float; - ens_max[i] = bad_data_float; - ens_range[i] = bad_data_float; } else { @@ -2844,13 +2788,6 @@ void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { ens_mean[i] = (float) (sum_na[i]/cnt_na[i]); ens_stdev[i] = (float) compute_stdev(stdev_sum_na[i], stdev_ssq_na[i], nint(stdev_cnt_na[i])); - ens_minus[i] = (float) ens_mean[i] - ens_stdev[i]; - ens_plus[i] = (float) ens_mean[i] + ens_stdev[i]; - ens_min[i] = (float) min_na[i]; - ens_max[i] = (float) max_na[i]; - v = max_na[i] - min_na[i]; - if(is_eq(v, 0.0)) v = 0; - ens_range[i] = (float) v; } } // end for i @@ -2868,41 +2805,6 @@ void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { "Ensemble Standard Deviation"); } - // Add the ensemble mean minus one standard deviation, if requested - if(conf_info.nc_info.do_minus) { - write_ens_var_float(ens_info, ens_minus, ens_dp, - "ENS_MINUS", - "Ensemble Mean Minus 1 Standard Deviation"); - } - - // Add the ensemble mean plus one standard deviation, if requested - if(conf_info.nc_info.do_plus) { - write_ens_var_float(ens_info, ens_plus, ens_dp, - "ENS_PLUS", - "Ensemble Mean Plus 1 Standard Deviation"); - } - - // Add the ensemble minimum value, if requested - if(conf_info.nc_info.do_min) { - write_ens_var_float(ens_info, ens_min, ens_dp, - "ENS_MIN", - "Ensemble Minimum"); - } - - // Add the ensemble maximum value, if requested - if(conf_info.nc_info.do_max) { - write_ens_var_float(ens_info, ens_max, ens_dp, - "ENS_MAX", - "Ensemble Maximum"); - } - - // Add the ensemble range, if requested - if(conf_info.nc_info.do_range) { - write_ens_var_float(ens_info, ens_range, ens_dp, - "ENS_RANGE", - "Ensemble Range"); - } - // Add the ensemble valid data count, if requested if(conf_info.nc_info.do_vld) { write_ens_var_int(ens_info, ens_vld, ens_dp, @@ -2910,110 +2812,9 @@ void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { "Ensemble Valid Data Count"); } - // Add the ensemble relative frequencies and neighborhood probabilities, if requested - if(conf_info.nc_info.do_freq || - conf_info.nc_info.do_nep) { - - prob_dp.set_size(grid.nx(), grid.ny()); - - // Loop through each threshold - for(i=0; icat_ta.n(); i++) { - - // Initialize - prob_dp.erase(); - - // Compute the ensemble relative frequency - for(j=0; jcat_ta[i].get_abbr_str().contents().c_str()); - write_ens_data_plane(ens_info, prob_dp, ens_dp, type_str, - "Ensemble Relative Frequency"); - } - - // Write the neighborhood ensemble probability - if(conf_info.nc_info.do_nep) { - GaussianInfo info; - - // Loop over the neighborhoods - for(j=0; jcat_ta[i].get_abbr_str().contents().c_str(), - interpmthd_to_string(InterpMthd_Nbrhd).c_str(), - conf_info.nbrhd_prob.width[j]*conf_info.nbrhd_prob.width[j]); - write_ens_data_plane(ens_info, nbrhd_dp, ens_dp, type_str, - "Neighborhood Ensemble Probability"); - } // end for j - } // end if do_nep - } // end for i - } // end if - - // Add the neighborhood maximum ensemble probabilities, if requested - if(conf_info.nc_info.do_nmep) { - - prob_dp.set_size(grid.nx(), grid.ny()); - - // Loop through each threshold - for(i=0; icat_ta.n(); i++) { - - // Loop through each neigbhorhood size - for(j=0; jcat_ta[i].get_abbr_str().contents().c_str(), - interpmthd_to_string(InterpMthd_Nbrhd).c_str(), - conf_info.nbrhd_prob.width[j]*conf_info.nbrhd_prob.width[j], - conf_info.nmep_smooth.method[k].c_str(), - conf_info.nmep_smooth.width[k]*conf_info.nmep_smooth.width[k]); - write_ens_data_plane(ens_info, nbrhd_dp, ens_dp, type_str, - "Neighborhood Maximum Ensemble Probability"); - } // end for k - } // end for j - } // end for i - } // end if do_nep - // Deallocate and clean up if(ens_mean) { delete [] ens_mean; ens_mean = (float *) 0; } if(ens_stdev) { delete [] ens_stdev; ens_stdev = (float *) 0; } - if(ens_minus) { delete [] ens_minus; ens_minus = (float *) 0; } - if(ens_plus) { delete [] ens_plus; ens_plus = (float *) 0; } - if(ens_min) { delete [] ens_min; ens_min = (float *) 0; } - if(ens_max) { delete [] ens_max; ens_max = (float *) 0; } - if(ens_range) { delete [] ens_range; ens_range = (float *) 0; } if(ens_vld) { delete [] ens_vld; ens_vld = (int *) 0; } return; @@ -3414,26 +3215,6 @@ void clean_up() { << "Output file: " << out_nc_file_list[i] << "\n"; } - // Deallocate threshold count arrays - if(thresh_cnt_na) { - for(i=0; inc_var_str = parse_conf_string(&i_edict, conf_key_nc_var_str, false); - // Conf: ens_nc_pairs - // Only parse thresholds if probabilities are requested - if(nc_info.do_freq || nc_info.do_nep || nc_info.do_nmep) { - - // Conf: cat_thresh - ens_info->cat_ta = i_edict.lookup_thresh_array(conf_key_cat_thresh); - - // Dump the contents of the current thresholds - if(mlog.verbosity_level() >= 5) { - mlog << Debug(5) - << "Parsed thresholds for ensemble field number " << i+1 << ":\n"; - ens_info->cat_ta.dump(cout); - } - - // Keep track of the maximum number of thresholds - if(ens_info->cat_ta.n() > max_n_ens_thresh) { - max_n_ens_thresh = ens_info->cat_ta.n(); - } - } - ens_input.push_back(ens_info); } // end for i @@ -362,40 +338,6 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, exit(1); } - // Conf: nbrhd_prob - nbrhd_prob = parse_conf_nbrhd(&conf, conf_key_nbrhd_prob); - n_nbrhd = nbrhd_prob.width.n(); - - // Conf: nmep_smooth - nmep_smooth = parse_conf_interp(&conf, conf_key_nmep_smooth); - - // Loop through the neighborhood probability smoothing options - for(i=0; i " - << "Neighborhood probability smoothing methods DW_MEAN, " - << "LS_FIT, and BILIN are not supported for \"" - << conf_key_nmep_smooth << "\".\n\n"; - exit(1); - } - - // Check for valid neighborhood probability interpolation widths - if(nmep_smooth.width[i] < 1 || nmep_smooth.width[i]%2 == 0) { - mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "Neighborhood probability smoothing widths must be set " - << "to odd values greater than or equal to 1 (" - << nmep_smooth.width[i] << ") for \"" - << conf_key_nmep_smooth << "\".\n\n"; - exit(1); - } - } // end for i - // Conf: fcst.field and obs.field fdict = conf.lookup_array(conf_key_fcst_field); odict = conf.lookup_array(conf_key_obs_field); @@ -508,15 +450,7 @@ void EnsembleStatConfInfo::parse_nc_info() { nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); nc_info.do_stdev = d->lookup_bool(conf_key_stdev_flag); - nc_info.do_minus = d->lookup_bool(conf_key_minus_flag); - nc_info.do_plus = d->lookup_bool(conf_key_plus_flag); - nc_info.do_min = d->lookup_bool(conf_key_min_flag); - nc_info.do_max = d->lookup_bool(conf_key_max_flag); - nc_info.do_range = d->lookup_bool(conf_key_range_flag); nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); - nc_info.do_freq = d->lookup_bool(conf_key_frequency_flag); - nc_info.do_nep = d->lookup_bool(conf_key_nep_flag); - nc_info.do_nmep = d->lookup_bool(conf_key_nmep_flag); nc_info.do_orank = d->lookup_bool(conf_key_rank_flag); nc_info.do_weight = d->lookup_bool(conf_key_weight); @@ -1316,10 +1250,8 @@ void EnsembleStatNcOutInfo::clear() { bool EnsembleStatNcOutInfo::all_false() const { - bool status = do_latlon || do_mean || do_stdev || do_minus || - do_plus || do_min || do_max || do_range || - do_vld || do_freq || do_nep || do_nmep || - do_orank || do_weight; + bool status = do_latlon || do_mean || do_stdev || + do_vld || do_orank || do_weight; return(!status); } @@ -1331,15 +1263,7 @@ void EnsembleStatNcOutInfo::set_all_false() { do_latlon = false; do_mean = false; do_stdev = false; - do_minus = false; - do_plus = false; - do_min = false; - do_max = false; - do_range = false; do_vld = false; - do_freq = false; - do_nep = false; - do_nmep = false; do_orank = false; do_weight = false; @@ -1354,15 +1278,7 @@ void EnsembleStatNcOutInfo::set_all_true() { do_latlon = true; do_mean = true; do_stdev = true; - do_minus = true; - do_plus = true; - do_min = true; - do_max = true; - do_range = true; do_vld = true; - do_freq = true; - do_nep = true; - do_nmep = true; do_orank = true; do_weight = true; @@ -1370,4 +1286,3 @@ void EnsembleStatNcOutInfo::set_all_true() { } //////////////////////////////////////////////////////////////////////// - diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index e2d823a504..eac46bed1f 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -55,15 +55,7 @@ struct EnsembleStatNcOutInfo { bool do_latlon; bool do_mean; bool do_stdev; - bool do_minus; - bool do_plus; - bool do_min; - bool do_max; - bool do_range; bool do_vld; - bool do_freq; - bool do_nep; - bool do_nmep; bool do_orank; bool do_weight; @@ -198,7 +190,6 @@ class EnsembleStatConfInfo { // Ensemble processing int n_ens_var; // Number of ensemble fields to be processed - int max_n_ens_thresh; // Maximum number of ensemble thresholds // Ensemble verification int n_vx; // Number of ensemble fields to be verified @@ -222,10 +213,6 @@ class EnsembleStatConfInfo { StringArray ens_member_ids; // Array of ensemble member ID strings ConcatString control_id; // Control ID - NbrhdInfo nbrhd_prob; // Neighborhood probability definition - int n_nbrhd; // Number of neighborhood sizes - InterpInfo nmep_smooth; // Neighborhood maximum smoothing information - EnsembleStatVxOpt * vx_opt; // Array of vx task options [n_vx] (allocated) double vld_ens_thresh; // Required ratio of valid input files @@ -266,7 +253,6 @@ class EnsembleStatConfInfo { // Dump out the counts int get_n_ens_var() const; - int get_n_nbrhd() const; int get_n_vx() const; // Compute the maximum number of output lines possible based @@ -275,7 +261,6 @@ class EnsembleStatConfInfo { int n_stat_row() const; // Maximum across all verification tasks - int get_max_n_ens_thresh() const; int get_max_hira_size() const; int get_max_n_prob_cat_thresh() const; int get_max_n_prob_pct_thresh() const; @@ -287,9 +272,7 @@ class EnsembleStatConfInfo { //////////////////////////////////////////////////////////////////////// inline int EnsembleStatConfInfo::get_n_ens_var() const { return(n_ens_var); } -inline int EnsembleStatConfInfo::get_n_nbrhd() const { return(n_nbrhd); } inline int EnsembleStatConfInfo::get_n_vx() const { return(n_vx); } -inline int EnsembleStatConfInfo::get_max_n_ens_thresh() const { return(max_n_ens_thresh); } inline int EnsembleStatConfInfo::get_max_hira_size() const { return(max_hira_size); } inline int EnsembleStatConfInfo::get_compression_level() { return(conf.nc_compression()); } From d5005a8ecbe4fdf475f8d7409fe68b235cb7533b Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Thu, 8 Sep 2022 13:53:39 -0600 Subject: [PATCH 02/23] Per #1908, remove min_na and max_na since theyare no longer needed. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 6 ------ src/tools/core/ensemble_stat/ensemble_stat.h | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 1b3250f400..cf3c53d11f 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -1967,8 +1967,6 @@ void clear_counts() { int i, j; cnt_na.set_const(0.0, nxy); - min_na.set_const(bad_data_double, nxy); - max_na.set_const(bad_data_double, nxy); sum_na.set_const(0.0, nxy); stdev_cnt_na.set_const(0.0, nxy); @@ -2006,10 +2004,6 @@ void track_counts(EnsVarInfo * ens_info, const DataPlane &ens_dp, bool is_ctrl) // Ensemble sum sum_na.buf()[i] += v; - // Ensemble min and max - if(v <= min_na.buf()[i] || is_bad_data(min_na.buf()[i])) min_na.buf()[i] = v; - if(v >= max_na.buf()[i] || is_bad_data(max_na.buf()[i])) max_na.buf()[i] = v; - // Standard deviation sum, sum of squares, and count, excluding control member if(!is_ctrl) { stdev_sum_na.buf()[i] += v; diff --git a/src/tools/core/ensemble_stat/ensemble_stat.h b/src/tools/core/ensemble_stat/ensemble_stat.h index 478938710d..17f4b8bd6d 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.h +++ b/src/tools/core/ensemble_stat/ensemble_stat.h @@ -184,7 +184,7 @@ static Met2dDataFileFactory mtddf_factory; static StatHdrColumns shc; // Arrays to store running sums and counts -static NumArray cnt_na, min_na, max_na, sum_na; +static NumArray cnt_na, sum_na; static NumArray stdev_cnt_na, stdev_sum_na, stdev_ssq_na; //////////////////////////////////////////////////////////////////////// From 5f9739eb165e9c5ec2d2309b5597daa8f936fd05 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Thu, 8 Sep 2022 16:07:41 -0600 Subject: [PATCH 03/23] Per #1908, get rid of fcst_file_list and fcst_file_vld arrays and just use ens_file_list and ens_file_vld instead. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 35 +++++-------------- src/tools/core/ensemble_stat/ensemble_stat.h | 2 -- .../ensemble_stat/ensemble_stat_conf_info.cc | 15 ++++---- .../ensemble_stat/ensemble_stat_conf_info.h | 2 +- 4 files changed, 17 insertions(+), 37 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index cf3c53d11f..d3f0cdbb34 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -317,9 +317,6 @@ void process_command_line(int argc, char **argv) { exit(1); } - // Copy ensemble file list to forecast file list - fcst_file_list = ens_file_list; - // Append the control member, if specified if(ctrl_file.nonempty()) { @@ -331,8 +328,8 @@ void process_command_line(int argc, char **argv) { } // Add control member file to end of the forecast file list - fcst_file_list.add(ctrl_file.c_str()); - ctrl_file_index = fcst_file_list.n()-1; + ens_file_list.add(ctrl_file.c_str()); + ctrl_file_index = ens_file_list.n()-1; } // Check that the end_ut >= beg_ut @@ -408,7 +405,8 @@ void process_command_line(int argc, char **argv) { } // Process the configuration - conf_info.process_config(etype, otype, grid_obs_flag, point_obs_flag, use_var_id, &ens_file_list, &fcst_file_list, ctrl_file.nonempty()); + conf_info.process_config(etype, otype, grid_obs_flag, point_obs_flag, + use_var_id, &ens_file_list, ctrl_file.nonempty()); // Set the model name shc.set_model(conf_info.model.c_str()); @@ -457,21 +455,6 @@ void process_command_line(int argc, char **argv) { } } - // Check for missing non-python forecast files - for(i=0; i " - << "can't open input forecast file: " - << fcst_file_list[i] << "\n\n"; - fcst_file_vld.add(0); - } - else { - fcst_file_vld.add(1); - } - } - // Set flag to indicate whether verification is to be performed if((point_obs_flag || grid_obs_flag) && (conf_info.get_n_vx() > 0) && @@ -693,7 +676,7 @@ void process_n_vld() { j = conf_info.vx_opt[i_var].vx_pd.fcst_info->get_file_index(i_ens); // Check for valid file - if(!fcst_file_vld[j]) continue; + if(!ens_file_vld[j]) continue; // Check for valid data fields. // Call data_plane_array to handle multiple levels. @@ -969,7 +952,7 @@ void process_vx() { // Determine the index of the control member in list of data values int ctrl_data_index = (is_bad_data(ctrl_file_index) ? - bad_data_int : fcst_file_vld.sum()-1); + bad_data_int : ens_file_vld.sum()-1); // Setup the PairDataEnsemble objects conf_info.set_vx_pd(n_vx_vld, ctrl_data_index); @@ -1031,7 +1014,7 @@ void process_point_vx() { i_file = conf_info.vx_opt[0].vx_pd.fcst_info->get_file_index(i); // If the current forecast file is valid, process it - if(!fcst_file_vld[i_file]) { + if(!ens_file_vld[i_file]) { n_miss++; continue; } @@ -1266,7 +1249,7 @@ int process_point_ens(int i_ens, int &n_miss) { int i_file = conf_info.vx_opt[0].vx_pd.fcst_info->get_file_index(i_ens); // Determine the correct file to process - if(!is_ens_mean) ens_file = ConcatString(fcst_file_list[i_file]); + if(!is_ens_mean) ens_file = ConcatString(ens_file_list[i_file]); else ens_file = (ens_mean_user.empty() ? ens_mean_file : ens_mean_user); @@ -1545,7 +1528,7 @@ void process_grid_vx() { fcst_file = conf_info.vx_opt[i].vx_pd.fcst_info->get_file(j); // If the current ensemble file is valid, read the field - if(fcst_file_vld[i_file]) { + if(ens_file_vld[i_file]) { found = get_data_plane(fcst_file.c_str(), etype, var_info, fcst_dp[j], true); diff --git a/src/tools/core/ensemble_stat/ensemble_stat.h b/src/tools/core/ensemble_stat/ensemble_stat.h index 17f4b8bd6d..6847edca01 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.h +++ b/src/tools/core/ensemble_stat/ensemble_stat.h @@ -98,9 +98,7 @@ static IntArray n_ens_vld; // Number of members with valid data for each static IntArray n_vx_vld; // Number of members with valid data for each verification field [n_vx] static StringArray ens_file_list; // Array of ensemble input files -static StringArray fcst_file_list; // Array of ensemble input files including control static IntArray ens_file_vld; // Array of ensemble file valid status -static IntArray fcst_file_vld; // Array of forecast file valid status static GrdFileType etype = FileType_None; static bool ens_mean_flag; // Flag for ensemble mean processing diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 51c8067afa..754d5eb13c 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -128,7 +128,6 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, bool grid_vx, bool point_vx, bool use_var_id, StringArray * ens_files, - StringArray * fcst_files, bool use_ctrl) { int i, j, n_ens_files; VarInfoFactory info_factory; @@ -383,7 +382,7 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, vx_opt[i].process_config(etype, i_fdict, otype, i_odict, rng_ptr, grid_vx, point_vx, use_var_id, ens_member_ids, - fcst_files, use_ctrl, control_id); + ens_files, use_ctrl, control_id); // For no point verification, store obtype as the message type if(!point_vx) { @@ -753,7 +752,7 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, gsl_rng *rng_ptr, bool grid_vx, bool point_vx, bool use_var_id, StringArray ens_member_ids, - StringArray * fcst_files, + StringArray * ens_files, bool use_ctrl, ConcatString control_id) { int i, j; VarInfoFactory info_factory; @@ -782,16 +781,16 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, input_info.var_info = next_var; input_info.file_index = 0; - input_info.file_list = fcst_files; + input_info.file_list = ens_files; vx_pd.fcst_info->add_input(input_info); // Add InputInfo to fcst info list for each ensemble file provided // set var_info to NULL to note first VarInfo should be used - int last_member_index = fcst_files->n() - (use_ctrl ? 1 : 0); + int last_member_index = ens_files->n() - (use_ctrl ? 1 : 0); for(j=1; jadd_input(input_info); } // end for j } // end for i @@ -809,8 +808,8 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, next_var->set_dict(fdict); input_info.var_info = next_var; - input_info.file_index = fcst_files->n() - 1; - input_info.file_list = fcst_files; + input_info.file_index = ens_files->n() - 1; + input_info.file_list = ens_files; vx_pd.fcst_info->add_input(input_info); } diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index eac46bed1f..2ad3a7fb9d 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -245,7 +245,7 @@ class EnsembleStatConfInfo { void read_config (const ConcatString , const ConcatString); void process_config(GrdFileType, GrdFileType, bool, bool, bool, - StringArray *, StringArray *, bool); + StringArray *, bool); void process_flags (); void parse_nc_info (); void process_masks (const Grid &); From bbb073491b1c821e648153e8eb80bbc9be441c1f Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Thu, 8 Sep 2022 16:21:25 -0600 Subject: [PATCH 04/23] Per #1908, remove vx_flag since verification is no longer optional. Ensure that obs files are provided. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 35 ++++++------------- src/tools/core/ensemble_stat/ensemble_stat.h | 15 +------- 2 files changed, 12 insertions(+), 38 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index d3f0cdbb34..9a33ea2682 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -199,8 +199,8 @@ int met_main(int argc, char *argv[]) { // Process the ensemble fields process_ensemble(); - // Only perform verification if requested - if(vx_flag) process_vx(); + // Perform verification + process_vx(); // Close the text files and deallocate memory clean_up(); @@ -377,6 +377,14 @@ void process_command_line(int argc, char **argv) { // Use a variable index from var_name instead of GRIB code bool use_var_id = false; + // Observation files are required + if(!grid_obs_flag && !point_obs_flag) { + mlog << Error << "\nprocess_command_line() -> " + << "the \"-grid_obs\" or \"-point_obs\" command line option " + << "must be used at least once.\n\n"; + exit(1); + } + // Determine the input observation file type if(point_obs_flag) { otype = FileType_Gb1; @@ -455,22 +463,6 @@ void process_command_line(int argc, char **argv) { } } - // Set flag to indicate whether verification is to be performed - if((point_obs_flag || grid_obs_flag) && - (conf_info.get_n_vx() > 0) && - (conf_info.output_flag[i_ecnt] != STATOutputType_None || - conf_info.output_flag[i_rhist] != STATOutputType_None || - conf_info.output_flag[i_phist] != STATOutputType_None || - conf_info.output_flag[i_ssvar] != STATOutputType_None || - conf_info.output_flag[i_relp] != STATOutputType_None || - conf_info.output_flag[i_orank] != STATOutputType_None || - conf_info.output_flag[i_pct] != STATOutputType_None || - conf_info.output_flag[i_pstd] != STATOutputType_None || - conf_info.output_flag[i_pjc] != STATOutputType_None || - conf_info.output_flag[i_prc] != STATOutputType_None || - conf_info.output_flag[i_eclv] != STATOutputType_None)) vx_flag = true; - else vx_flag = false; - // Process ensemble mean information ens_mean_flag = false; bool need_ens_mean = ( @@ -492,11 +484,6 @@ void process_command_line(int argc, char **argv) { << ens_mean_user << "\n\n"; ens_mean_user = ""; } - else if(!vx_flag) { - mlog << Warning << "\nprocess_command_line() -> " - << "ignoring input -ens_mean file because no verification " - << "has been requested\n\n"; - } else { ens_mean_flag = true; } @@ -3184,7 +3171,7 @@ void clean_up() { mlog << Debug(2) << "\n" << sep_str << "\n\n"; // Close the output text files that were open for writing - if(vx_flag) finish_txt_files(); + finish_txt_files(); // List the output NetCDF files for(i=0; i Date: Fri, 9 Sep 2022 14:35:31 -0600 Subject: [PATCH 05/23] Per #1908, error out if no vx tasks are defined. --- .../ensemble_stat/ensemble_stat_conf_info.cc | 108 +++++++----------- 1 file changed, 44 insertions(+), 64 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 754d5eb13c..3ac0aa16d9 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -96,8 +96,6 @@ void EnsembleStatConfInfo::clear() { ens_input.clear(); // Reset counts - n_ens_var = 0; - n_vx = 0; max_hira_size = 0; @@ -229,22 +227,14 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, // If no ensemble member IDs were provided, add an empty string if(ens_member_ids.n() == 0) ens_member_ids.add(""); - // Conf: ens.field - edict = conf.lookup_array(conf_key_ens_field); - - // Determine the number of ensemble fields to be processed - n_ens_var = parse_conf_n_vx(edict); - - // Print a warning if the ensemble dictionary is not empty - if(n_ens_var != 0) { + // Conf: ens, print warning if present + if(conf.lookup_dictionary(conf_key_ens)) { mlog << Warning << "\nEnsembleStatConfInfo::process_config() -> " - << "Ensemble post-processing should be moved to the " - << "Gen-Ens-Prod tool, which replaces the logic of the " - << "\"ens\" dictionary. Support for the \"ens\" dictionary " - << "will be deprecated and removed." << "\n\n"; + << "support for ensemble product generation with the \"ens\" " + << "dictionary has moved to the Gen-Ens-Prod tool." << "\n\n"; } - - // Parse the ensemble field information + + // Parse the ensemble field information for(i=0; i " << "The number of verification tasks in \"" - << conf_key_obs_field - << "\" must match the number in \"" - << conf_key_fcst_field << "\".\n\n"; + << conf_key_obs_field << "\" (" << n_ovx + << ") must be non-zero and match the number in \"" + << conf_key_fcst_field << "\" (" << n_fvx << ").\n\n"; exit(1); } - if(n_vx > 0) { - - // Allocate memory for the verification task options - vx_opt = new EnsembleStatVxOpt [n_vx]; - - // Check climatology fields - check_climo_n_vx(&conf, n_vx); + // Allocate memory for the verification task options + n_vx = n_fvx; + vx_opt = new EnsembleStatVxOpt [n_vx]; - // Check to make sure the observation file type is defined - if(otype == FileType_None) { - mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "When \"fcst.field\" is non-empty, you must use " - << "\"-point_obs\" and/or \"-grid_obs\" to specify the " - << "verifying observations.\n\n"; - exit(1); - } + // Check climatology fields + check_climo_n_vx(&conf, n_vx); - // Parse settings for each verification task - for(i=0,max_hira_size=0; isize()); - } + // Track the maximum HiRA size + for(j=0; jsize()); } } - - // Summarize output flags across all verification tasks - process_flags(); } + // Summarize output flags across all verification tasks + process_flags(); + return; } From a5ec2a83df709bafe4ab31670c6094e04b34b1b6 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sat, 17 Sep 2022 10:38:46 -0600 Subject: [PATCH 06/23] Per #1908, ci-skip-unit work in progress. Doesn't actually compile yet. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 8 +- .../ensemble_stat/ensemble_stat_conf_info.cc | 92 +------------------ .../ensemble_stat/ensemble_stat_conf_info.h | 8 +- 3 files changed, 8 insertions(+), 100 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 9a33ea2682..f8ae830324 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -106,7 +106,6 @@ using namespace std; static void process_command_line (int, char **); static void process_grid (const Grid &); static void process_n_vld (); -static void process_ensemble (); static void process_vx (); static bool get_data_plane (const char *, GrdFileType, VarInfo *, DataPlane &, bool do_regrid); @@ -196,9 +195,6 @@ int met_main(int argc, char *argv[]) { // Check for valid ensemble data process_n_vld(); - // Process the ensemble fields - process_ensemble(); - // Perform verification process_vx(); @@ -817,7 +813,7 @@ bool get_data_plane_array(const char *infile, GrdFileType ftype, } //////////////////////////////////////////////////////////////////////// - +/* JHG void process_ensemble() { int i_var, i_ens, j; bool reset; @@ -918,7 +914,7 @@ void process_ensemble() { return; } - +*/ //////////////////////////////////////////////////////////////////////// void process_vx() { diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 3ac0aa16d9..eae2f56429 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -62,7 +62,6 @@ void EnsembleStatConfInfo::init_from_scratch() { void EnsembleStatConfInfo::clear() { int i; - vector::const_iterator it = ens_input.begin(); // Initialize values model.clear(); @@ -88,16 +87,9 @@ void EnsembleStatConfInfo::clear() { // Deallocate memory if(vx_opt) { delete [] vx_opt; vx_opt = (EnsembleStatVxOpt *) 0; } - for(; it != ens_input.end(); it++) { - - if(*it) { delete *it; } - - } - ens_input.clear(); - // Reset counts - n_vx = 0; - max_hira_size = 0; + n_vx = 0; + max_hira_size = 0; return; } @@ -130,12 +122,10 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, int i, j, n_ens_files; VarInfoFactory info_factory; mapoutput_map; - Dictionary *edict = (Dictionary *) 0; Dictionary *fdict = (Dictionary *) 0; Dictionary *odict = (Dictionary *) 0; - Dictionary i_edict, i_fdict, i_odict; + Dictionary i_fdict, i_odict; InterpMthd mthd; - VarInfo * next_var; // Dump the contents of the config file if(mlog.verbosity_level() >= 5) conf.dump(cout); @@ -201,9 +191,8 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, // Only a single file should be provided if using ens_member_ids if(ens_files->n() > 1) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The \"" << conf_key_ens_member_ids << "\" " - << "must be empty if more than " - << "one file is provided.\n\n"; + << "the \"" << conf_key_ens_member_ids << "\" " + << "must be empty if more than one file is provided.\n\n"; exit(1); } @@ -234,77 +223,6 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, << "dictionary has moved to the Gen-Ens-Prod tool." << "\n\n"; } - // Parse the ensemble field information - for(i=0; iraw_magic_str = raw_magic_str(i_edict, etype); - - // Loop over ensemble member IDs to substitute - for(j=0; jset_dict(i_edict); - - // Dump the contents of the current VarInfo - if(mlog.verbosity_level() >= 5) { - mlog << Debug(5) - << "Parsed ensemble field number " << i+1 - << " (" << j+1 << "):\n"; - next_var->dump(cout); - } - - InputInfo input_info; - input_info.var_info = next_var; - input_info.file_index = 0; - input_info.file_list = ens_files; - ens_info->add_input(input_info); - - // Add InputInfo to ens info list for each ensemble file provided - // set var_info to NULL to note first VarInfo should be used - for(int k=1; kadd_input(input_info); - } // end for k - } // end for j - - // Get field info for control member if set - if(!control_id.empty()) { - - // Set environment variable for ens member ID - setenv(met_ens_member_id, control_id.c_str(), 1); - - // Allocate new VarInfo object - next_var = info_factory.new_var_info(etype); - - // Set the current dictionary - next_var->set_dict(i_edict); - - ens_info->set_ctrl(next_var); - } - - // Conf: ens_nc_var_str - ens_info->nc_var_str = parse_conf_string(&i_edict, conf_key_nc_var_str, false); - - ens_input.push_back(ens_info); - } // end for i - - // Unset MET_ENS_MEMBER_ID that was previously set - unsetenv(met_ens_member_id); - // Conf: ens.ens_thresh vld_ens_thresh = conf.lookup_double(conf_key_ens_ens_thresh); diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index 2ad3a7fb9d..e503fa7fe4 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -188,9 +188,6 @@ class EnsembleStatConfInfo { void init_from_scratch(); - // Ensemble processing - int n_ens_var; // Number of ensemble fields to be processed - // Ensemble verification int n_vx; // Number of ensemble fields to be verified int max_hira_size; // Maximum size of a HiRA neighborhoods @@ -209,7 +206,6 @@ class EnsembleStatConfInfo { ConcatString model; // Model name ConcatString obtype; // Observation type - vector ens_input; // Vector of EnsVarInfo pointers (allocated) StringArray ens_member_ids; // Array of ensemble member ID strings ConcatString control_id; // Control ID @@ -252,8 +248,7 @@ class EnsembleStatConfInfo { void set_vx_pd (const IntArray &, int); // Dump out the counts - int get_n_ens_var() const; - int get_n_vx() const; + int get_n_vx() const; // Compute the maximum number of output lines possible based // on the contents of the configuration file @@ -271,7 +266,6 @@ class EnsembleStatConfInfo { //////////////////////////////////////////////////////////////////////// -inline int EnsembleStatConfInfo::get_n_ens_var() const { return(n_ens_var); } inline int EnsembleStatConfInfo::get_n_vx() const { return(n_vx); } inline int EnsembleStatConfInfo::get_max_hira_size() const { return(max_hira_size); } inline int EnsembleStatConfInfo::get_compression_level() { return(conf.nc_compression()); } From 9bfb382579e5ad1abfba4418a7c0fd66906debf6 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 12:18:23 -0600 Subject: [PATCH 07/23] Per #1908, change list of config file names to lookup. --- src/basic/vx_config/config_constants.h | 34 ++++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/src/basic/vx_config/config_constants.h b/src/basic/vx_config/config_constants.h index e4b4d4d75a..d23d4bf724 100644 --- a/src/basic/vx_config/config_constants.h +++ b/src/basic/vx_config/config_constants.h @@ -731,10 +731,8 @@ static const char conf_key_wvlt_plot[] = "wvlt_plot"; // Ensemble-Stat specific parameter key names // -static const char conf_key_ens[] = "ens"; -static const char conf_key_ens_field[] = "ens.field"; -static const char conf_key_ens_ens_thresh[] = "ens.ens_thresh"; -static const char conf_key_ens_vld_thresh[] = "ens.vld_thresh"; +static const char conf_key_fcst_ens_thresh[] = "fcst.ens_thresh"; +static const char conf_key_fcst_vld_thresh[] = "fcst.vld_thresh"; static const char conf_key_nc_var_str[] = "nc_var_str"; static const char conf_key_nbrhd_prob[] = "nbrhd_prob"; static const char conf_key_nmep_smooth[] = "nmep_smooth"; @@ -742,17 +740,6 @@ static const char conf_key_skip_const[] = "skip_const"; static const char conf_key_rng_type[] = "rng.type"; static const char conf_key_rng_seed[] = "rng.seed"; static const char conf_key_ensemble_flag[] = "ensemble_flag"; -static const char conf_key_mean_flag[] = "mean"; -static const char conf_key_stdev_flag[] = "stdev"; -static const char conf_key_minus_flag[] = "minus"; -static const char conf_key_plus_flag[] = "plus"; -static const char conf_key_min_flag[] = "min"; -static const char conf_key_max_flag[] = "max"; -static const char conf_key_range_flag[] = "range"; -static const char conf_key_vld_count_flag[] = "vld_count"; -static const char conf_key_frequency_flag[] = "frequency"; -static const char conf_key_nep_flag[] = "nep"; -static const char conf_key_nmep_flag[] = "nmep"; static const char conf_key_rank_flag[] = "rank"; static const char conf_key_ssvar_bin[] = "ens_ssvar_bin_size"; static const char conf_key_phist_bin[] = "ens_phist_bin_size"; @@ -768,7 +755,22 @@ static const char conf_key_inst_bias_offset[] = "inst_bias_offset"; // Gen-Ens-Prod specific parameter key names // -static const char conf_key_normalize[] = "normalize"; +static const char conf_key_ens[] = "ens"; +static const char conf_key_ens_field[] = "ens.field"; +static const char conf_key_ens_ens_thresh[] = "ens.ens_thresh"; +static const char conf_key_ens_vld_thresh[] = "ens.vld_thresh"; +static const char conf_key_normalize[] = "normalize"; +static const char conf_key_mean_flag[] = "mean"; +static const char conf_key_stdev_flag[] = "stdev"; +static const char conf_key_minus_flag[] = "minus"; +static const char conf_key_plus_flag[] = "plus"; +static const char conf_key_min_flag[] = "min"; +static const char conf_key_max_flag[] = "max"; +static const char conf_key_range_flag[] = "range"; +static const char conf_key_vld_count_flag[] = "vld_count"; +static const char conf_key_frequency_flag[] = "frequency"; +static const char conf_key_nep_flag[] = "nep"; +static const char conf_key_nmep_flag[] = "nmep"; // Distribution options static const char conf_val_normal[] = "NORMAL"; From c1f4ce95096118122114c1581a0e2bc2d5aaad29 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 12:19:10 -0600 Subject: [PATCH 08/23] Per #1908, define operator += and operator /= functions for the DataPlane and DataPlaneArray classes. --- src/basic/vx_util/data_plane.cc | 86 ++++++++++++++++++++++++++++++++- src/basic/vx_util/data_plane.h | 6 ++- 2 files changed, 90 insertions(+), 2 deletions(-) diff --git a/src/basic/vx_util/data_plane.cc b/src/basic/vx_util/data_plane.cc index 618627dd63..bde7f982bc 100644 --- a/src/basic/vx_util/data_plane.cc +++ b/src/basic/vx_util/data_plane.cc @@ -69,6 +69,51 @@ DataPlane & DataPlane::operator=(const DataPlane &d) { /////////////////////////////////////////////////////////////////////////////// +DataPlane & DataPlane::operator+=(const DataPlane &d) { + const char *method_name = "DataPlane::operator+=(const DataPlane &) -> "; + + // Check for matching dimensions + if(Nx != d.Nx || Ny != d.Ny) { + mlog << Error << "\n" << method_name + << "the dimensions do not match: (" + << Nx << ", " << Ny << ") != (" + << d.Nx << ", " << d.Ny << ")\n\n"; + exit(1); + } + + // Increment values, checking for bad data + double v; + for(int i=0; i & buf(); @@ -187,6 +189,8 @@ class DataPlaneArray { ~DataPlaneArray(); DataPlaneArray(const DataPlaneArray &); DataPlaneArray & operator=(const DataPlaneArray &); + DataPlaneArray & operator+=(const DataPlaneArray &); + DataPlaneArray & operator/=(const double); void clear(); From bee6c0e79e098434fd353bcefc2269ffd3f87dae Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 12:20:15 -0600 Subject: [PATCH 09/23] Per #1908, work in progress stripping out the ensemble processing. It compiles and runs, but I still need to do more testing and refinement. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 853 ++++-------------- src/tools/core/ensemble_stat/ensemble_stat.h | 14 +- .../ensemble_stat/ensemble_stat_conf_info.cc | 33 +- .../ensemble_stat/ensemble_stat_conf_info.h | 3 +- 4 files changed, 218 insertions(+), 685 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 27d549eecd..fa1aeb3d34 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -113,9 +113,8 @@ static bool get_data_plane_array (const char *, GrdFileType, VarInfo *, DataPlaneArray &, bool do_regrid); static void process_point_vx (); -static void process_point_climo (); static void process_point_obs (int); -static int process_point_ens (int, int &); +static bool process_point_ens (int, int, DataPlaneArray &); static void process_point_scores (); static void process_grid_vx (); @@ -133,11 +132,6 @@ static void do_rps (const EnsembleStatVxOpt &, const SingleThresh &, const PairDataEnsemble *); -static void clear_counts(); -static void track_counts(EnsVarInfo *, const DataPlane &, bool); - -static ConcatString get_ens_mn_var_name(int); - static void setup_nc_file (unixtime, const char *); static void setup_txt_files (); static void setup_table (AsciiTable &); @@ -151,14 +145,6 @@ static void do_pct_cat_thresh(const EnsembleStatVxOpt &, const PairDataEnsemble static void do_pct_cdp_thresh(const EnsembleStatVxOpt &, const PairDataEnsemble &); static void write_pct_info(const EnsembleStatVxOpt &, const PCTInfo *, int, bool); -static void write_ens_nc(EnsVarInfo *, int, DataPlane &); -static void write_ens_var_float(EnsVarInfo *, float *, const DataPlane &, - const char *, const char *); -static void write_ens_var_int(EnsVarInfo *, int *, const DataPlane &, - const char *, const char *); -static void write_ens_data_plane(EnsVarInfo *, const DataPlane &, const DataPlane &, - const char *, const char *); - static void write_orank_nc(PairDataEnsemble &, DataPlane &, int, int, int); static void write_orank_var_float(int, int, int, float *, DataPlane &, const char *, const char *); @@ -357,7 +343,7 @@ void process_command_line(int argc, char **argv) { conf_info.read_config(default_config_file, config_file); // Get the ensemble file type from config, if present - etype = parse_conf_file_type(conf_info.conf.lookup_dictionary(conf_key_ens)); + etype = parse_conf_file_type(conf_info.conf.lookup_dictionary(conf_key_fcst)); // Read the first input ensemble file if(!(ens_mtddf = mtddf_factory.new_met_2d_data_file(ens_file_list[0].c_str(), etype))) { @@ -459,43 +445,17 @@ void process_command_line(int argc, char **argv) { } } - // Process ensemble mean information - ens_mean_flag = false; - bool need_ens_mean = ( - conf_info.output_flag[i_ecnt] != STATOutputType_None || - conf_info.output_flag[i_orank] != STATOutputType_None || - conf_info.output_flag[i_ssvar] != STATOutputType_None); - // User-specified ensemble mean file - if(ens_mean_user.nonempty()) { - - if(!need_ens_mean) { - mlog << Warning << "\nprocess_command_line() -> " - << "ignoring input -ens_mean file because no ensemble " - << "mean is needed.\n\n"; - } - else if(!file_exists(ens_mean_user.c_str())) { + if(ens_mean_file.nonempty()) { + if(!file_exists(ens_mean_file.c_str())) { mlog << Warning << "\nprocess_command_line() -> " << "can't open input ensemble mean file: " - << ens_mean_user << "\n\n"; - ens_mean_user = ""; - } - else { - ens_mean_flag = true; - } - } - else if(need_ens_mean) { - - ens_mean_flag = true; - - if(!conf_info.nc_info.do_mean) { - mlog << Warning << "\nprocess_command_line() -> " - << "enabling NetCDF ensemble mean computation to be used " - << "in verification.\n\n"; - conf_info.nc_info.do_mean = true; + << ens_mean_file << "\n\n"; + ens_mean_file = ""; } } + // User-specified ensemble control file if(conf_info.control_id.nonempty() && ctrl_file.empty()) { mlog << Warning << "\nprocess_command_line() -> " << "control_id is set in the config file but " @@ -516,18 +476,7 @@ void process_grid(const Grid &fcst_grid) { // Parse regridding logic RegridInfo ri; - if(conf_info.ens_input.size() > 0) { - ri = conf_info.ens_input[0]->get_var_info()->regrid(); - } - else if(conf_info.get_n_vx() > 0) { - ri = conf_info.vx_opt[0].vx_pd.fcst_info->get_var_info()->regrid(); - } - else { - mlog << Error << "\nprocess_grid() -> " - << "at least one ensemble field or verification field must " - << "be provided!\n\n"; - exit(1); - } + ri = conf_info.vx_opt[0].vx_pd.fcst_info->get_var_info()->regrid(); // Read gridded observation data, if necessary if(ri.field == FieldType_Obs) { @@ -584,76 +533,21 @@ void process_n_vld() { DataPlane dp; DataPlaneArray dpa; VarInfo * var_info; - ConcatString ens_file, fcst_file; + ConcatString fcst_file; vector::const_iterator var_it; // Initialize - n_ens_vld.clear(); n_vx_vld.clear(); - // Loop through the ensemble fields to be processed - if(conf_info.ens_input.size() > 0) { - var_it = conf_info.ens_input.begin(); - n_ens_inputs = (*var_it)->inputs_n(); - } - else { - n_ens_inputs = 0; - } - - for(i_var=0; var_it != conf_info.ens_input.end(); var_it++, i_var++) { - - // Loop through the ensemble inputs - for(i_ens=n_vld=0; i_ens < n_ens_inputs; i_ens++) { - - // Get file and VarInfo to process - ens_file = (*var_it)->get_file(i_ens); - var_info = (*var_it)->get_var_info(i_ens); - - // Check for valid file - if(!ens_file_vld[(*var_it)->get_file_index(i_ens)]) continue; - - // Check for valid data - if(!get_data_plane(ens_file.c_str(), etype, - var_info, dp, false)) { - mlog << Warning << "\nprocess_n_vld() -> " - << "ensemble field \"" - << var_info->magic_str() - << "\" not found in file \"" << ens_file - << "\"\n\n"; - } - else { - - // Increment the valid counter - n_vld++; - } - } // end for i_ens - - // Check for enough valid data - if((double) n_vld/n_ens_inputs < conf_info.vld_ens_thresh) { - mlog << Error << "\nprocess_n_vld() -> " - << n_vld << " of " << n_ens_inputs - << " (" << (double)n_vld/n_ens_inputs << ")" - << " fields found for \"" << (*var_it)->get_var_info()->magic_str() - << "\" does not meet the threshold specified by \"" - << conf_key_ens_ens_thresh << "\" (" << conf_info.vld_ens_thresh - << ") in the configuration file.\n\n"; - exit(1); - } - - // Store the valid data count - n_ens_vld.add(n_vld); - - } // end for i_var - // Loop through the verification fields to be processed for(i_var=0; i_varinputs_n(); // Loop through the forecast inputs - for(i_ens=n_vld=0; i_ens < n_ens_inputs; i_ens++) { + for(i_ens=n_vld=0; i_ensget_file(i_ens); var_info = conf_info.vx_opt[i_var].vx_pd.fcst_info->get_var_info(i_ens); j = conf_info.vx_opt[i_var].vx_pd.fcst_info->get_file_index(i_ens); @@ -686,11 +580,11 @@ void process_n_vld() { if((double) n_vld/n_ens_inputs < conf_info.vld_ens_thresh) { mlog << Error << "\nprocess_n_vld() -> " << n_vld << " of " << n_ens_inputs - << " (" << (double)n_vld/n_ens_inputs << ")" + << " (" << (double) n_vld/n_ens_inputs << ")" << " forecast fields found for \"" << conf_info.vx_opt[i_var].vx_pd.fcst_info->get_var_info()->magic_str() << "\" does not meet the threshold specified by \"" - << conf_key_ens_ens_thresh << "\" (" << conf_info.vld_ens_thresh + << conf_key_fcst_ens_thresh << "\" (" << conf_info.vld_ens_thresh << ") in the configuration file.\n\n"; exit(1); } @@ -812,140 +706,25 @@ bool get_data_plane_array(const char *infile, GrdFileType ftype, return(found); } -//////////////////////////////////////////////////////////////////////// -/* JHG -void process_ensemble() { - int i_var, i_ens, j; - bool reset; - DataPlane ens_dp, ctrl_dp; - unixtime max_init_ut = bad_data_ll; - VarInfo * var_info; - VarInfo * ctrl_info; - ConcatString ens_file; - - vector::const_iterator var_it = conf_info.ens_input.begin(); - - // Loop through each of the ensemble fields to be processed - for(i_var=0; var_it != conf_info.ens_input.end(); var_it++, i_var++) { - - var_info = (*var_it)->get_var_info(); - - mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Processing ensemble field: " - << (*var_it)->raw_magic_str << "\n"; - - // Loop through each of the input forecast files/variables - for(i_ens=0,reset=true; i_ens < (*var_it)->inputs_n(); i_ens++) { - - j = (*var_it)->get_file_index(i_ens); - - // Skip bad data files - if(!ens_file_vld[j]) { continue; } - - // get file and VarInfo to process - ens_file = (*var_it)->get_file(i_ens); - var_info = (*var_it)->get_var_info(i_ens); - - mlog << Debug(3) << "\n" - << "Reading field: " - << var_info->magic_str() << "\n"; - - // Read the current field - if(!get_data_plane(ens_file.c_str(), etype, - var_info, ens_dp, true)) { continue; } - - // Create a NetCDF file to store the ensemble output - if(nc_out == (NcFile *) 0) { - setup_nc_file(ens_dp.valid(), "_ens.nc"); - } - - // Reset the running sums and counts - if(reset) { - clear_counts(); - reset = false; - - // Read ensemble control member data, if provided - if(ctrl_file.nonempty()) { - ctrl_info = (*var_it)->get_ctrl(i_ens); - - mlog << Debug(3) << "\n" - << "Reading control field: " - << ctrl_info->magic_str() << "\n"; - - // Error out if missing - if (!get_data_plane(ctrl_file.c_str(), etype, - ctrl_info, ctrl_dp, true)) { - mlog << Error << "\nprocess_ensemble() -> " - << "control member ensemble field \"" - << ctrl_info->magic_str() - << "\" not found in file \"" << ctrl_file << "\"\n\n"; - exit(1); - } - - // Apply current data to the running sums and counts - track_counts(*var_it, ctrl_dp, true); - } - } - - // Apply current data to the running sums and counts - track_counts(*var_it, ens_dp, false); - - // Keep track of the maximum initialization time - if(is_bad_data(max_init_ut) || ens_dp.init() > max_init_ut) { - max_init_ut = ens_dp.init(); - } - - } // end for i_ens - - // Write out the ensemble information to a NetCDF file - ens_dp.set_init(max_init_ut); - write_ens_nc(*var_it, i_var, ens_dp); - - // Store the ensemble mean output file - ens_mean_file = out_nc_file_list[out_nc_file_list.n() - 1]; - - } // end for var_it - - // Close the output NetCDF file - if(nc_out) { - delete nc_out; - nc_out = (NcFile *) 0; - } - - return; -} -*/ //////////////////////////////////////////////////////////////////////// void process_vx() { - if(conf_info.get_n_vx() > 0) { + // Process masks Grids and Polylines in the config file + conf_info.process_masks(grid); - if(point_obs_file_list.n() == 0 && - grid_obs_file_list.n() == 0) { - mlog << Error << "\nprocess_vx() -> " - << "when \"fcst.field\" is non-empty, you must use " - << "\"-point_obs\" and/or \"-grid_obs\" to specify the " - << "verifying observations.\n\n"; - exit(1); - } - - // Process masks Grids and Polylines in the config file - conf_info.process_masks(grid); + // Determine the index of the control member in list of data values + int ctrl_data_index = (is_bad_data(ctrl_file_index) ? + bad_data_int : ens_file_vld.sum()-1); - // Determine the index of the control member in list of data values - int ctrl_data_index = (is_bad_data(ctrl_file_index) ? - bad_data_int : ens_file_vld.sum()-1); + // Setup the PairDataEnsemble objects + conf_info.set_vx_pd(n_vx_vld, ctrl_data_index); - // Setup the PairDataEnsemble objects - conf_info.set_vx_pd(n_vx_vld, ctrl_data_index); + // Process the point observations + if(point_obs_flag) process_point_vx(); - // Process the point observations - if(point_obs_flag) process_point_vx(); - - // Process the gridded observations - if(grid_obs_flag) process_grid_vx(); - } + // Process the gridded observations + if(grid_obs_flag) process_grid_vx(); return; } @@ -953,19 +732,22 @@ void process_vx() { //////////////////////////////////////////////////////////////////////// void process_point_vx() { - int i, i_file, n_miss; + int i, j, i_file, n_miss; unixtime beg_ut, end_ut; + DataPlaneArray fcst_dpa, emn_dpa; + DataPlaneArray cmn_dpa, csd_dpa; - // Set observation time window for each verification task + // Loop through each of the fields to be verified for(i=0; iget_var_info()->magic_str() << ".\n"; + + // Store climatology information + conf_info.vx_opt[i].vx_pd.set_climo_mn_dpa(cmn_dpa); + conf_info.vx_opt[i].vx_pd.set_climo_sd_dpa(csd_dpa); } + // Process each point observation NetCDF file + for(i=0; iinputs_n(); i++) { + // Loop through each of the fields to be verified + for(i=0; iget_file_index(i); + // Initialize + emn_dpa.clear(); - // If the current forecast file is valid, process it - if(!ens_file_vld[i_file]) { - n_miss++; - continue; - } - else { - process_point_ens(i, n_miss); - } + // Loop through the ensemble inputs + for(j=0, n_miss=0; jinputs_n(); j++) { - } // end for i + i_file = conf_info.vx_opt[i].vx_pd.fcst_info->get_file_index(j); - // Process the ensemble mean, if necessary - if(ens_mean_flag) process_point_ens(-1, n_miss); + // If the current forecast file is valid, process it + if(!ens_file_vld[i_file]) { + n_miss++; + continue; + } + else if(!process_point_ens(i, j, fcst_dpa)) { + n_miss++; + continue; + } - // Compute the scores and write them out - process_point_scores(); + // Store ensemble member data + conf_info.vx_opt[i].vx_pd.set_fcst_dpa(fcst_dpa); - return; -} + // Compute ensemble values for this member + conf_info.vx_opt[i].vx_pd.add_ens(j-n_miss, false, grid); -//////////////////////////////////////////////////////////////////////// + // Running sum for the ensemble mean + if(emn_dpa.n_planes() == 0) emn_dpa = fcst_dpa; + else emn_dpa += fcst_dpa; -void process_point_climo() { - int i; - DataPlaneArray cmn_dpa, csd_dpa; + } // end for j - // Loop through each of the fields to be verified and extract - // the climatology fields for verification - for(i=0; iget_var_info(); + + // Read the gridded data from the ensemble mean file + if(!get_data_plane_array(ens_mean_file.c_str(), info->file_type(), info, + emn_dpa, true)) { + mlog << Error << "\nprocess_point_vx() -> " + << "trouble reading the ensemble mean field \"" + << info->magic_str() << "\" from file \"" + << ens_mean_file << "\"\n\n"; + exit(1); + } + + // Dump out the number of levels found + mlog << Debug(2) << "For " << info->magic_str() + << " found " << emn_dpa.n_planes() << " forecast levels.\n"; + + } + // Otherwise, compute the ensemble mean from the members + else { + + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Computing the ensemble mean from the members.\n"; + + int n = conf_info.vx_opt[i].vx_pd.fcst_info->inputs_n() - n_miss; + + if(n <= 0) { + mlog << Error << "\nprocess_point_vx() -> " + << "all inputs are missing!\n\n"; + exit(1); + } + + // Convert running sums to a mean + emn_dpa /= (double) n; + } + + // Store ensemble mean data + conf_info.vx_opt[i].vx_pd.set_fcst_dpa(emn_dpa); + + // Compute ensemble mean values + conf_info.vx_opt[i].vx_pd.add_ens(-1, true, grid); } // end for i + // Compute the scores and write them out + process_point_scores(); + return; } @@ -1217,78 +1048,29 @@ void process_point_obs(int i_nc) { //////////////////////////////////////////////////////////////////////// -int process_point_ens(int i_ens, int &n_miss) { - int i; - DataPlaneArray fcst_dpa; - NumArray fcst_lvl_na; - VarInfo *info = (VarInfo *) 0; - VarInfoNcMet ens_mean_info; - - ConcatString ens_file; - bool is_ens_mean = (-1 == i_ens); - const char *file_type = (is_ens_mean ? "mean" : "ensemble"); +bool process_point_ens(int i_vx, int i_ens, DataPlaneArray &fcst_dpa) { - // get file index from first verification for logging - int i_file = conf_info.vx_opt[0].vx_pd.fcst_info->get_file_index(i_ens); + // Initialize + fcst_dpa.clear(); - // Determine the correct file to process - if(!is_ens_mean) ens_file = ConcatString(ens_file_list[i_file]); - else ens_file = (ens_mean_user.empty() ? - ens_mean_file : ens_mean_user); + // Get file based on current vx and ensemble index + ConcatString ens_file = conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_file(i_ens); mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Processing " << file_type << " file: " << ens_file + << "Processing ensemble member file: " << ens_file << (i_ens == ctrl_file_index ? " (control)\n" : "\n"); - // Loop through each of the fields to be verified and extract - // the forecast fields for verification - for(i=0; iget_var_info(i_ens); - } - - // If not processing mean, get file based on current vx and ensemble index - if(!is_ens_mean) ens_file = conf_info.vx_opt[i].vx_pd.fcst_info->get_file(i_ens); - - // Read the gridded data from the input forecast file - if(!get_data_plane_array(ens_file.c_str(), info->file_type(), info, - fcst_dpa, true)) { - - // Error out if unable to read the ensemble mean - if(is_ens_mean) { - mlog << Error << "\nprocess_point_ens() -> " - << "trouble reading the ensemble mean field \"" - << info->magic_str() << "\" from file \"" - << ens_file << "\"\n\n"; - exit(1); - } - - n_miss++; - continue; - } - - // Dump out the number of levels found - mlog << Debug(2) << "For " << info->magic_str() - << " found " << fcst_dpa.n_planes() << " forecast levels.\n"; + VarInfo *info = conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_var_info(i_ens); - // Store information for the raw forecast fields - conf_info.vx_opt[i].vx_pd.set_fcst_dpa(fcst_dpa); + // Read the gridded data from the input forecast file + bool status = get_data_plane_array(ens_file.c_str(), info->file_type(), info, + fcst_dpa, true); - // Compute forecast values for this ensemble member - conf_info.vx_opt[i].vx_pd.add_ens(i_ens-n_miss, is_ens_mean, grid); + // Dump out the number of levels found + mlog << Debug(2) << "For " << info->magic_str() + << " found " << fcst_dpa.n_planes() << " forecast levels.\n"; - } // end for i - - return(0); + return(status); } //////////////////////////////////////////////////////////////////////// @@ -1505,6 +1287,7 @@ void process_grid_vx() { // Initialize fcst_dp[j].clear(); + emn_dp.clear(); i_file = conf_info.vx_opt[i].vx_pd.fcst_info->get_file_index(j); var_info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info(j); @@ -1513,20 +1296,62 @@ void process_grid_vx() { // If the current ensemble file is valid, read the field if(ens_file_vld[i_file]) { found = get_data_plane(fcst_file.c_str(), etype, - var_info, - fcst_dp[j], true); + var_info, fcst_dp[j], true); } else { found = false; } + // Running sum for the ensemble mean + if(found) { + if(emn_dp.is_empty()) emn_dp = fcst_dp[j]; + else emn_dp += fcst_dp[j]; + } // Count the number of missing files - if(!found) { + else { n_miss++; continue; } } // end for j + // Read the ensemble mean from a file + if(ens_mean_file.nonempty()) { + + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Processing ensemble mean file: " << ens_mean_file << "\n"; + + VarInfo *info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info(); + + // Read the gridded data from the mean file + found = get_data_plane(ens_mean_file.c_str(), FileType_None, + info, emn_dp, true); + + if(!found) { + mlog << Error << "\nprocess_grid_vx() -> " + << "trouble reading ensemble mean field \"" + << info->magic_str() << "\" from file \"" + << ens_mean_file << "\"\n\n"; + exit(1); + } + } + // Otherwise, compute the ensemble mean from the members + else { + + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Computing the ensemble mean from the members.\n"; + + int n = conf_info.vx_opt[i].vx_pd.fcst_info->inputs_n() - n_miss; + + if(n <= 0) { + mlog << Error << "\nprocess_grid_vx() -> " + << "all inputs are missing!\n\n"; + exit(1); + } + + // Convert running sums to a mean + emn_dp /= (double) n; + } + // Read climatology data cmn_dp = read_climo_data_plane( conf_info.conf.lookup_array(conf_key_climo_mean_field, false), @@ -1543,9 +1368,9 @@ void process_grid_vx() { // If requested in the config file, create a NetCDF file to store // the verification matched pairs - if(conf_info.nc_info.do_orank && - nc_out == (NcFile *) 0) + if(!conf_info.nc_info.all_false() && nc_out == (NcFile *) 0) { setup_nc_file(fcst_dp[j].valid(), "_orank.nc"); + } // Read the observation file for(j=0, n_miss=0; jget_var_info(); - } - - // Read the gridded data from the mean file - found = get_data_plane(mn_file.c_str(), FileType_None, - info, emn_dp, true); - - if(!found) { - mlog << Error << "\nprocess_grid_vx() -> " - << "trouble reading ensemble mean field \"" - << info->magic_str() << "\" from file \"" - << mn_file << "\"\n\n"; - exit(1); - } - } - // Loop through and apply each of the smoothing operations for(j=0; jcat_ta.n(); - SingleThresh *thr_buf = ens_info->cat_ta.buf(); - - // Increment counts for each grid point - for(i=0; iget_var_info()->name_attr() << "_" - << conf_info.vx_opt[i_vx].vx_pd.fcst_info->get_var_info()->level_attr() - << "_ENS_MEAN"; - cs.replace(",", "_", false); - cs.replace("*", "all", false); - mlog << Debug(4) << "Generated mean field: " << cs << "\n"; - - return(cs); -} - -//////////////////////////////////////////////////////////////////////// - void setup_nc_file(unixtime valid_ut, const char *suffix) { ConcatString out_nc_file; @@ -2714,193 +2436,6 @@ void write_pct_info(const EnsembleStatVxOpt &vx_opt, //////////////////////////////////////////////////////////////////////// -void write_ens_nc(EnsVarInfo * ens_info, int i_var, DataPlane &ens_dp) { - int i, j, k, l; - double t, v; - char type_str[max_str_len]; - - // Allocate memory for storing ensemble data - float * ens_mean = new float [nxy]; - float * ens_stdev = new float [nxy]; - int * ens_vld = new int [nxy]; - - // Store the threshold for the ratio of valid data points - t = conf_info.vld_data_thresh; - - // Store the data - for(i=0; inc_var_str; - if(cs.length() > 0) var_str << "_" << cs; - - // Construct the variable name - ens_var_name << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << ens_info->get_var_info()->level_attr() - << var_str << "_" << type_str; - - // Skip variable names that have already been written - if(nc_ens_var_sa.has(ens_var_name)) return; - - // Otherwise, add to the list of previously defined variables - nc_ens_var_sa.add(ens_var_name); - ens_var = add_var(nc_out, (string)ens_var_name, ncFloat, lat_dim, lon_dim); - - // - // Construct the variable name attribute - // For the ensemble mean, just use the variable name. - // For all other fields, append the field type. - // - if(strcmp(type_str, "ENS_MEAN") == 0) { - name_str << cs_erase - << ens_info->get_var_info()->name_attr(); - } - else { - name_str << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << type_str; - } - - // Add the variable attributes - add_var_att_local(ens_info->get_var_info(), &ens_var, false, dp, - name_str.c_str(), long_name_str); - - // Write the data - if(!put_nc_data_with_dims(&ens_var, &ens_data[0], grid.ny(), grid.nx())) { - mlog << Error << "\nwrite_ens_var_float() -> " - << "error in ens_var->put for the " << ens_var_name - << " field.\n\n"; - exit(1); - } - - return; -} - -//////////////////////////////////////////////////////////////////////// - -void write_ens_var_int(EnsVarInfo * ens_info, int *ens_data, const DataPlane &dp, - const char *type_str, - const char *long_name_str) { - NcVar ens_var; - ConcatString ens_var_name, var_str, name_str, cs; - - // Append nc_pairs_var_str config file entry - cs = ens_info->nc_var_str; - if(cs.length() > 0) var_str << "_" << cs; - - // Construct the variable name - ens_var_name << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << ens_info->get_var_info()->level_attr() - << var_str << "_" << type_str; - - // Skip variable names that have already been written - if(nc_ens_var_sa.has(ens_var_name)) return; - - // Otherwise, add to the list of previously defined variables - nc_ens_var_sa.add(ens_var_name); - - int deflate_level = compress_level; - if (deflate_level < 0) deflate_level = conf_info.get_compression_level(); - ens_var = add_var(nc_out, (string)ens_var_name, ncInt, lat_dim, lon_dim, deflate_level); - - // Construct the variable name attribute - name_str << cs_erase - << ens_info->get_var_info()->name_attr() << "_" - << type_str; - - // Add the variable attributes - add_var_att_local(ens_info->get_var_info(), &ens_var, true, dp, - name_str.c_str(), long_name_str); - - // Write the data - if(!put_nc_data_with_dims(&ens_var, &ens_data[0], grid.ny(), grid.nx())) { - mlog << Error << "\nwrite_ens_var_int() -> " - << "error in ens_var->put for the " << ens_var_name - << " field.\n\n"; - exit(1); - } - - return; -} - -//////////////////////////////////////////////////////////////////////// - -void write_ens_data_plane(EnsVarInfo * ens_info, const DataPlane &ens_dp, const DataPlane &dp, - const char *type_str, const char *long_name_str) { - - // Allocate memory for this data - float *ens_data = new float [nxy]; - - // Store the data in an array of floats - for(int i=0; i 1.0) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The \"" << conf_key_ens_ens_thresh << "\" parameter (" + << "The \"" << conf_key_fcst_ens_thresh << "\" parameter (" << vld_ens_thresh << ") must be set between 0 and 1.\n\n"; exit(1); } - // Conf: ens.vld_thresh - vld_data_thresh = conf.lookup_double(conf_key_ens_vld_thresh); + // Conf: fcst.vld_thresh + vld_data_thresh = conf.lookup_double(conf_key_fcst_vld_thresh); // Check that the valid data threshold is between 0 and 1. if(vld_data_thresh < 0.0 || vld_data_thresh > 1.0) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The \"" << conf_key_ens_vld_thresh << "\" parameter (" + << "The \"" << conf_key_fcst_vld_thresh << "\" parameter (" << vld_data_thresh << ") must be set between 0 and 1.\n\n"; exit(1); } @@ -256,10 +256,10 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, // Check for a valid number of verification tasks if(n_fvx == 0 || n_fvx != n_ovx) { mlog << Error << "\nEnsembleStatConfInfo::process_config() -> " - << "The number of verification tasks in \"" - << conf_key_obs_field << "\" (" << n_ovx - << ") must be non-zero and match the number in \"" - << conf_key_fcst_field << "\" (" << n_fvx << ").\n\n"; + << "The number of \"" << conf_key_obs_field << "\" entries (" + << n_ovx << ") must be greater than zero and match " + << "the number of \"" << conf_key_fcst_field << "\" entries (" + << n_fvx << ").\n\n"; exit(1); } @@ -345,9 +345,8 @@ void EnsembleStatConfInfo::parse_nc_info() { Dictionary * d = e->dict_value(); nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); - nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); - nc_info.do_stdev = d->lookup_bool(conf_key_stdev_flag); nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); + nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); nc_info.do_orank = d->lookup_bool(conf_key_rank_flag); nc_info.do_weight = d->lookup_bool(conf_key_weight); @@ -1147,8 +1146,8 @@ void EnsembleStatNcOutInfo::clear() { bool EnsembleStatNcOutInfo::all_false() const { - bool status = do_latlon || do_mean || do_stdev || - do_vld || do_orank || do_weight; + bool status = do_latlon || do_vld || do_mean || + do_orank || do_weight; return(!status); } @@ -1158,9 +1157,8 @@ bool EnsembleStatNcOutInfo::all_false() const { void EnsembleStatNcOutInfo::set_all_false() { do_latlon = false; - do_mean = false; - do_stdev = false; do_vld = false; + do_mean = false; do_orank = false; do_weight = false; @@ -1173,9 +1171,8 @@ void EnsembleStatNcOutInfo::set_all_false() { void EnsembleStatNcOutInfo::set_all_true() { do_latlon = true; - do_mean = true; - do_stdev = true; do_vld = true; + do_mean = true; do_orank = true; do_weight = true; diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index e503fa7fe4..6871fc1b57 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -53,9 +53,8 @@ static const STATLineType txt_file_type[n_txt] = { struct EnsembleStatNcOutInfo { bool do_latlon; - bool do_mean; - bool do_stdev; bool do_vld; + bool do_mean; bool do_orank; bool do_weight; From 827ea38672a17a056d920b197e4b13df4c4d3931 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 12:20:50 -0600 Subject: [PATCH 10/23] Per #1908, remove ens dictionary from the Ensemble-Stat config file. Move vld_thresh and ens_thresh into the fcst dictionary. --- data/config/EnsembleStatConfig_default | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/data/config/EnsembleStatConfig_default b/data/config/EnsembleStatConfig_default index ddea4f8743..e5f730f7a0 100644 --- a/data/config/EnsembleStatConfig_default +++ b/data/config/EnsembleStatConfig_default @@ -45,22 +45,6 @@ censor_val = []; cat_thresh = []; nc_var_str = ""; -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "APCP"; - level = "A03"; - cat_thresh = [ >0.0, >=5.0 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -89,6 +73,9 @@ eclv_points = 0.05; // Forecast and observation fields to be verified // fcst = { + vld_thresh = 1.0; + ens_thresh = 1.0; + field = [ { name = "APCP"; @@ -258,9 +245,8 @@ output_flag = { // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; vld_count = TRUE; + mean = TRUE; rank = TRUE; weight = FALSE; } From 9d10b5ea91a38d03ebe97ff61e414b1d7e892517 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 19:52:36 -0600 Subject: [PATCH 11/23] Per #1908, fix bug in when enm_dp should be initialized for gridded vx. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index fa1aeb3d34..373aee37f0 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -1211,6 +1211,9 @@ void process_grid_vx() { // Loop through each of the fields to be verified for(i=0; iget_file_index(j); var_info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info(j); From e9a32f2b552225fef1bcfe38dfa7d9ecd2c30d1c Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 20:07:17 -0600 Subject: [PATCH 12/23] Per #1908, only write orank nc output if requested. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 46 +++++++++++-------- .../ensemble_stat/ensemble_stat_conf_info.cc | 16 +++---- .../ensemble_stat/ensemble_stat_conf_info.h | 4 +- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 373aee37f0..5f4ac46c94 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -2480,30 +2480,36 @@ void write_orank_nc(PairDataEnsemble &pd, DataPlane &dp, } // end for i - // Add the observation values - write_orank_var_float(i_vx, i_interp, i_mask, obs_v, dp, - "OBS", - "Observation Value"); - - // Add the observation ranks - write_orank_var_int(i_vx, i_interp, i_mask, obs_rank, dp, - "OBS_RANK", - "Observation Rank"); - - // Add the probability integral transforms - write_orank_var_float(i_vx, i_interp, i_mask, obs_pit, dp, - "OBS_PIT", - "Probability Integral Transform"); + // Add the observation values and ranks + if(conf_info.nc_info.do_rank) { + write_orank_var_float(i_vx, i_interp, i_mask, obs_v, dp, + "OBS", + "Observation Value"); + + // Add the observation ranks + write_orank_var_int(i_vx, i_interp, i_mask, obs_rank, dp, + "OBS_RANK", + "Observation Rank"); + + // Add the probability integral transforms + write_orank_var_float(i_vx, i_interp, i_mask, obs_pit, dp, + "OBS_PIT", + "Probability Integral Transform"); + } // Add the number of valid ensemble members - write_orank_var_int(i_vx, i_interp, i_mask, ens_vld, dp, - "ENS_VLD", - "Ensemble Valid Data Count"); + if(conf_info.nc_info.do_vld) { + write_orank_var_int(i_vx, i_interp, i_mask, ens_vld, dp, + "ENS_VLD", + "Ensemble Valid Data Count"); + } // Add the ensemble mean values - write_orank_var_float(i_vx, i_interp, i_mask, ens_mean, dp, - "ENS_MEAN", - "Ensemble Mean"); + if(conf_info.nc_info.do_mean) { + write_orank_var_float(i_vx, i_interp, i_mask, ens_mean, dp, + "ENS_MEAN", + "Ensemble Mean"); + } // Deallocate and clean up if(obs_v) { delete [] obs_v; obs_v = (float *) 0; } diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 29c909b869..25aa6d2d26 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -345,10 +345,10 @@ void EnsembleStatConfInfo::parse_nc_info() { Dictionary * d = e->dict_value(); nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); + nc_info.do_weight = d->lookup_bool(conf_key_weight); + nc_info.do_orank = d->lookup_bool(conf_key_rank_flag); nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); - nc_info.do_orank = d->lookup_bool(conf_key_rank_flag); - nc_info.do_weight = d->lookup_bool(conf_key_weight); return; } @@ -1146,8 +1146,8 @@ void EnsembleStatNcOutInfo::clear() { bool EnsembleStatNcOutInfo::all_false() const { - bool status = do_latlon || do_vld || do_mean || - do_orank || do_weight; + bool status = do_latlon || do_weight || do_rank || + do_vld || do_mean; return(!status); } @@ -1157,10 +1157,10 @@ bool EnsembleStatNcOutInfo::all_false() const { void EnsembleStatNcOutInfo::set_all_false() { do_latlon = false; + do_weight = false; + do_orank = false; do_vld = false; do_mean = false; - do_orank = false; - do_weight = false; return; } @@ -1171,10 +1171,10 @@ void EnsembleStatNcOutInfo::set_all_false() { void EnsembleStatNcOutInfo::set_all_true() { do_latlon = true; + do_weight = true; + do_orank = true; do_vld = true; do_mean = true; - do_orank = true; - do_weight = true; return; } diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index 6871fc1b57..e90828a583 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -53,10 +53,10 @@ static const STATLineType txt_file_type[n_txt] = { struct EnsembleStatNcOutInfo { bool do_latlon; + bool do_weight; + bool do_orank; bool do_vld; bool do_mean; - bool do_orank; - bool do_weight; ////////////////////////////////////////////////////////////////// From ffe923b24bb41e44f0648c989d8fc91f046c8bbf Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 20:20:59 -0600 Subject: [PATCH 13/23] Per #1908, fix typo and don't error out if the ens dictionary isn't present. It shouldn't be there anymore! --- src/tools/core/ensemble_stat/ensemble_stat.cc | 2 +- src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 5f4ac46c94..89d9799ad3 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -2481,7 +2481,7 @@ void write_orank_nc(PairDataEnsemble &pd, DataPlane &dp, } // end for i // Add the observation values and ranks - if(conf_info.nc_info.do_rank) { + if(conf_info.nc_info.do_orank) { write_orank_var_float(i_vx, i_interp, i_mask, obs_v, dp, "OBS", "Observation Value"); diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 25aa6d2d26..263edf1aa8 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -217,7 +217,7 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, if(ens_member_ids.n() == 0) ens_member_ids.add(""); // Conf: ens, print warning if present - if(conf.lookup_dictionary(conf_key_ens)) { + if(conf.lookup_dictionary(conf_key_ens, false, false)) { mlog << Warning << "\nEnsembleStatConfInfo::process_config() -> " << "support for ensemble product generation with the \"ens\" " << "dictionary has moved to the Gen-Ens-Prod tool." << "\n\n"; From aa8922f190c18b8d12cfa09fcbdb6cf98e7913e4 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 20:34:32 -0600 Subject: [PATCH 14/23] Per #1908, work on log messages. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 89d9799ad3..3f00e5fe19 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -822,8 +822,8 @@ void process_point_vx() { // Read the ensemble mean from a file if(ens_mean_file.nonempty()) { - mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Processing ensemble mean file: " << ens_mean_file << "\n"; + mlog << Debug(2) << "Processing ensemble mean file: " + << ens_mean_file << "\n"; VarInfo *info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info(); @@ -845,8 +845,7 @@ void process_point_vx() { // Otherwise, compute the ensemble mean from the members else { - mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Computing the ensemble mean from the members.\n"; + mlog << Debug(2) << "Computing the ensemble mean from the members.\n"; int n = conf_info.vx_opt[i].vx_pd.fcst_info->inputs_n() - n_miss; @@ -1081,7 +1080,8 @@ void process_point_scores() { ConcatString cs; int i, j, k, l; - mlog << Debug(2) << "\n" << sep_str << "\n\n"; + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Verifying against point observations.\n"; // Create output text files as requested in the config file setup_txt_files(); @@ -1198,7 +1198,8 @@ void process_grid_vx() { VarInfo * var_info; ConcatString fcst_file; - mlog << Debug(2) << "\n" << sep_str << "\n\n"; + mlog << Debug(2) << "\n" << sep_str << "\n\n" + << "Verifying against gridded analyses.\n"; // Set the obtype column shc.set_obtype(conf_info.obtype.c_str()); @@ -1319,8 +1320,8 @@ void process_grid_vx() { // Read the ensemble mean from a file if(ens_mean_file.nonempty()) { - mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Processing ensemble mean file: " << ens_mean_file << "\n"; + mlog << Debug(2) << "Processing ensemble mean file: " + << ens_mean_file << "\n"; VarInfo *info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info(); @@ -1339,8 +1340,7 @@ void process_grid_vx() { // Otherwise, compute the ensemble mean from the members else { - mlog << Debug(2) << "\n" << sep_str << "\n\n" - << "Computing the ensemble mean from the members.\n"; + mlog << Debug(2) << "Computing the ensemble mean from the members.\n"; int n = conf_info.vx_opt[i].vx_pd.fcst_info->inputs_n() - n_miss; From f01eaaa08d9e1f725b46bc35e5f6ea58e154bf29 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 21:05:19 -0600 Subject: [PATCH 15/23] Per #1908, big overhaul to all of the Ensemble-Stat config file removing the config options related to ensemble post-processing. --- data/config/EnsembleStatConfig_default | 21 ++-- internal/test_unit/config/EnsembleStatConfig | 80 ++-------------- .../config/EnsembleStatConfig_MASK_SID | 79 ++------------- .../test_unit/config/EnsembleStatConfig_climo | 73 ++------------ .../config/EnsembleStatConfig_grid_weight | 72 +++----------- .../config/EnsembleStatConfig_one_cdf_bin | 56 ++--------- .../config/EnsembleStatConfig_python | 77 +++------------ .../config/EnsembleStatConfig_qty_inc_exc | 75 ++------------- .../EnsembleStatConfig_single_file_grib | 77 ++------------- .../config/EnsembleStatConfig_single_file_nc | 93 ++++-------------- .../test_unit/xml/unit_climatology_1.0deg.xml | 2 - internal/test_unit/xml/unit_ensemble_stat.xml | 11 --- internal/test_unit/xml/unit_grid_weight.xml | 3 - .../test_unit/xml/unit_met_test_scripts.xml | 1 - internal/test_unit/xml/unit_python.xml | 2 - .../test_unit/xml/unit_quality_filter.xml | 1 - scripts/config/EnsembleStatConfig | 96 ++----------------- 17 files changed, 115 insertions(+), 704 deletions(-) diff --git a/data/config/EnsembleStatConfig_default b/data/config/EnsembleStatConfig_default index e5f730f7a0..02d5a3f4fb 100644 --- a/data/config/EnsembleStatConfig_default +++ b/data/config/EnsembleStatConfig_default @@ -37,14 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -52,11 +44,11 @@ nc_var_str = ""; ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -67,14 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { - vld_thresh = 1.0; ens_thresh = 1.0; + vld_thresh = 1.0; field = [ { @@ -241,14 +234,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; + weight = FALSE; + rank = TRUE; vld_count = TRUE; mean = TRUE; - rank = TRUE; - weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig b/internal/test_unit/config/EnsembleStatConfig index 1e9c7cf244..cc5626c6a7 100644 --- a/internal/test_unit/config/EnsembleStatConfig +++ b/internal/test_unit/config/EnsembleStatConfig @@ -37,35 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { - name = "TMP"; - level = "Z2"; - cat_thresh = [ <=273.15, >273.15 ]; - }, - { - name = "APCP"; - level = "A24"; - cat_thresh = [ >0.0 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -73,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -115,12 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; message_type = [ "ADPSFC" ]; obs_quality_inc = []; obs_quality_exc = []; @@ -253,23 +200,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; weight = FALSE; + rank = TRUE; + vld_count = TRUE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_MASK_SID b/internal/test_unit/config/EnsembleStatConfig_MASK_SID index fab2c42267..356fdb3ec4 100644 --- a/internal/test_unit/config/EnsembleStatConfig_MASK_SID +++ b/internal/test_unit/config/EnsembleStatConfig_MASK_SID @@ -37,32 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { - name = "APCP"; - level = "A24"; - cat_thresh = [ >0.0 ]; - censor_thresh = [ ${CENSOR_THRESH} ]; - censor_val = [ ${CENSOR_VAL} ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -70,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -112,13 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { - message_type = [ "ADPSFC" ]; + ens_thresh = 0.75; + vld_thresh = 1.0; + message_type = [ "ADPSFC" ]; field = [ { @@ -242,23 +192,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = FALSE; - plus = FALSE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = FALSE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; - rank = FALSE; weight = FALSE; + rank = FALSE; + vld_count = FALSE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_climo b/internal/test_unit/config/EnsembleStatConfig_climo index f2018f80c6..0e693e23c8 100644 --- a/internal/test_unit/config/EnsembleStatConfig_climo +++ b/internal/test_unit/config/EnsembleStatConfig_climo @@ -37,27 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { name = "TMP"; level = "Z2"; }, - { name = "TMP"; level = "P850"; } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -65,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -107,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; + field = [ { name = "TMP"; level = "Z2"; message_type = [ "ADPSFC" ]; }, { name = "TMP"; level = "P850"; message_type = [ "ADPUPA" ]; } @@ -265,23 +221,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = FALSE; - mean = TRUE; - stdev = FALSE; - minus = FALSE; - plus = FALSE; - min = FALSE; - max = FALSE; - range = FALSE; - vld_count = FALSE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; weight = FALSE; + rank = TRUE; + vld_count = FALSE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_grid_weight b/internal/test_unit/config/EnsembleStatConfig_grid_weight index 011c18daed..52b15aec83 100644 --- a/internal/test_unit/config/EnsembleStatConfig_grid_weight +++ b/internal/test_unit/config/EnsembleStatConfig_grid_weight @@ -37,25 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -tmp_field = [ { name = "TMP"; level = [ "Z2" ]; } ]; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - field = tmp_field; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -63,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -105,12 +59,17 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; +tmp_field = [ { name = "TMP"; level = [ "Z2" ]; } ]; + // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; message_type = [ "APDSFC" ]; sid_inc = []; sid_exc = []; @@ -250,23 +209,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = FALSE; - minus = FALSE; - plus = FALSE; - min = FALSE; - max = FALSE; - range = FALSE; - vld_count = FALSE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; - rank = FALSE; weight = TRUE; + rank = FALSE; + vld_count = FLASE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin b/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin index a2fee38da0..a2036bf6e6 100644 --- a/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin +++ b/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin @@ -37,27 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 0.75; - vld_thresh = 1.0; - - field = [ - { name = "TMP"; level = "Z2"; }, - { name = "TMP"; level = "P850"; } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -65,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -107,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 0.75; + vld_thresh = 1.0; + field = [ { name = "TMP"; level = "Z2"; message_type = [ "ADPSFC" ]; }, { name = "TMP"; level = "P850"; message_type = [ "ADPUPA" ]; } diff --git a/internal/test_unit/config/EnsembleStatConfig_python b/internal/test_unit/config/EnsembleStatConfig_python index e51aeb9e8a..61bb4056b7 100644 --- a/internal/test_unit/config/EnsembleStatConfig_python +++ b/internal/test_unit/config/EnsembleStatConfig_python @@ -37,24 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - file_type = PYTHON_NUMPY; - field = [ { name = "${FCST_COMMAND}"; } ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -62,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -104,13 +59,20 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // -fcst = ens; -obs = { +fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + + file_type = PYTHON_NUMPY; + field = [ { name = "${FCST_COMMAND}"; } ]; +} +obs = { file_type = PYTHON_NUMPY; field = [ { name = "${OBS_COMMAND}"; } ]; } @@ -234,23 +196,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = FALSE; - minus = FALSE; - plus = FALSE; - min = FALSE; - max = FALSE; - range = FALSE; - vld_count = TRUE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; - rank = FALSE; weight = FALSE; + rank = FALSE; + vld_count = TRUE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc b/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc index cc0838f25e..44cd84fb69 100644 --- a/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc +++ b/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc @@ -37,30 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "TMP"; - level = [ "Z2" ]; - cat_thresh = [ <=273, >273 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -68,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -110,12 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; message_type = [ "ADPSFC" ]; sid_inc = []; sid_exc = []; @@ -257,23 +209,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; weight = FALSE; + rank = TRUE; + vld_count = TRUE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_single_file_grib b/internal/test_unit/config/EnsembleStatConfig_single_file_grib index e731c8074f..e6a0dfa7bd 100644 --- a/internal/test_unit/config/EnsembleStatConfig_single_file_grib +++ b/internal/test_unit/config/EnsembleStatConfig_single_file_grib @@ -37,31 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "PRMSL"; - level = "L0"; - lead_time = "06"; - GRIB_ens = "MET_ENS_MEMBER_ID"; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -69,38 +44,11 @@ ens = { ens_member_ids = ["+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10", "+11", "+12", "+13", "+14", "+15", "+16", "+17", "+18", "+19", "+20"]; control_id = "hi_res_ctl"; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -111,12 +59,16 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + field = [ { name = "PRMSL"; @@ -293,23 +245,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = FALSE; - plus = FALSE; - min = TRUE; - max = TRUE; - range = FALSE; - vld_count = TRUE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; weight = FALSE; + rank = TRUE; + vld_count = TRUE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_single_file_nc b/internal/test_unit/config/EnsembleStatConfig_single_file_nc index 285ea922fc..40c35ebc48 100644 --- a/internal/test_unit/config/EnsembleStatConfig_single_file_nc +++ b/internal/test_unit/config/EnsembleStatConfig_single_file_nc @@ -37,38 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Override the NetCDF CFS variable names and times -// -file_type = NETCDF_NCCF; -set_attr_init = "19820101"; -set_attr_valid = "19820701"; -set_attr_name = "TMP"; -set_attr_level = "Z2"; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "fcst"; - level = "(MET_ENS_MEMBER_ID,6,*,*)"; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -76,38 +44,11 @@ ens = { ens_member_ids = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23"]; control_id = "0"; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -118,12 +59,25 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; +// +// Override the NetCDF CFS variable names and times +// +file_type = NETCDF_NCCF; +set_attr_init = "19820101"; +set_attr_valid = "19820701"; +set_attr_name = "TMP"; +set_attr_level = "Z2"; + // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; + field = [ { name = "fcst"; @@ -297,23 +251,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = FALSE; - plus = FALSE; - min = TRUE; - max = TRUE; - range = FALSE; - vld_count = TRUE; - frequency = FALSE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; weight = FALSE; + rank = TRUE; + vld_count = TRUE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/xml/unit_climatology_1.0deg.xml b/internal/test_unit/xml/unit_climatology_1.0deg.xml index a357b5c8b1..a07d47ff6e 100644 --- a/internal/test_unit/xml/unit_climatology_1.0deg.xml +++ b/internal/test_unit/xml/unit_climatology_1.0deg.xml @@ -269,7 +269,6 @@ &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_prc.txt &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_pjc.txt &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_eclv.txt - &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_ens.nc &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_NCEP_1.0DEG_20120410_120000V_orank.nc @@ -299,7 +298,6 @@ &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_ONE_CDF_BIN_20120410_120000V.stat &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_ONE_CDF_BIN_20120410_120000V_ecnt.txt - &OUTPUT_DIR;/climatology_1.0deg/ensemble_stat_ONE_CDF_BIN_20120410_120000V_ens.nc diff --git a/internal/test_unit/xml/unit_ensemble_stat.xml b/internal/test_unit/xml/unit_ensemble_stat.xml index 98a97a4779..6ee7fd6153 100644 --- a/internal/test_unit/xml/unit_ensemble_stat.xml +++ b/internal/test_unit/xml/unit_ensemble_stat.xml @@ -52,7 +52,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_CMD_LINE_20120410_120000V_orank.nc @@ -88,7 +87,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.nc @@ -119,7 +117,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_20120410_120000V.stat &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_20120410_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_20120410_120000V_ens.nc @@ -147,7 +144,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CTRL_20120410_120000V.stat &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CTRL_20120410_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CTRL_20120410_120000V_ens.nc @@ -175,7 +171,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CENSOR_20120410_120000V.stat &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CENSOR_20120410_120000V_orank.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_MASK_SID_CENSOR_20120410_120000V_ens.nc @@ -210,7 +205,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SKIP_CONST_20120410_120000V_orank.nc @@ -246,7 +240,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_phist.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_orank.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_OBSERR_20120410_120000V_orank.nc @@ -268,7 +261,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_NO_CTRL_19820701_000000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_NO_CTRL_19820701_000000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_NO_CTRL_19820701_000000V_orank.nc @@ -291,7 +283,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_WITH_CTRL_19820701_000000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_WITH_CTRL_19820701_000000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_NC_WITH_CTRL_19820701_000000V_orank.nc @@ -313,7 +304,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_NO_CTRL_20160608_060000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_NO_CTRL_20160608_060000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_NO_CTRL_20160608_060000V_orank.nc @@ -336,7 +326,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_WITH_CTRL_20160608_060000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_WITH_CTRL_20160608_060000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_SINGLE_FILE_GRIB_WITH_CTRL_20160608_060000V_orank.nc diff --git a/internal/test_unit/xml/unit_grid_weight.xml b/internal/test_unit/xml/unit_grid_weight.xml index f355401441..ebf0b03bc5 100644 --- a/internal/test_unit/xml/unit_grid_weight.xml +++ b/internal/test_unit/xml/unit_grid_weight.xml @@ -96,7 +96,6 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V.stat - &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V_ens.nc @@ -121,7 +120,6 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V.stat - &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V_ens.nc @@ -146,7 +144,6 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V.stat - &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V_ens.nc diff --git a/internal/test_unit/xml/unit_met_test_scripts.xml b/internal/test_unit/xml/unit_met_test_scripts.xml index 9d0176c561..a92610f795 100644 --- a/internal/test_unit/xml/unit_met_test_scripts.xml +++ b/internal/test_unit/xml/unit_met_test_scripts.xml @@ -474,7 +474,6 @@ &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_prc.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_eclv.txt &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V.stat - &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_ens.nc &OUTPUT_DIR;/ensemble_stat/ensemble_stat_20100101_120000V_orank.nc diff --git a/internal/test_unit/xml/unit_python.xml b/internal/test_unit/xml/unit_python.xml index e0f2cfe781..9f1b785a36 100644 --- a/internal/test_unit/xml/unit_python.xml +++ b/internal/test_unit/xml/unit_python.xml @@ -361,7 +361,6 @@ &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V.stat - &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V_ens.nc @@ -562,7 +561,6 @@ &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_phist.txt &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.txt &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ssvar.txt - &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_ens.nc &OUTPUT_DIR;/python/ensemble_stat/ensemble_stat_FILE_LIST_20120410_120000V_orank.nc diff --git a/internal/test_unit/xml/unit_quality_filter.xml b/internal/test_unit/xml/unit_quality_filter.xml index cbf086e4d5..560f1d8fab 100644 --- a/internal/test_unit/xml/unit_quality_filter.xml +++ b/internal/test_unit/xml/unit_quality_filter.xml @@ -61,7 +61,6 @@ &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_ecnt.txt &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_rhist.txt &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_orank.txt - &OUTPUT_DIR;/quality_filter/ensemble_stat_QTY_INC_EXC_MADIS_VGS_20120409_120000V_ens.nc diff --git a/scripts/config/EnsembleStatConfig b/scripts/config/EnsembleStatConfig index 2dde84f7bb..f59e21ef9f 100644 --- a/scripts/config/EnsembleStatConfig +++ b/scripts/config/EnsembleStatConfig @@ -37,51 +37,6 @@ regrid = { //////////////////////////////////////////////////////////////////////////////// -// -// May be set separately in each "ens.field" entry -// -censor_thresh = []; -censor_val = []; -cat_thresh = []; -nc_var_str = ""; - -// -// Ensemble product fields to be processed -// -ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - - field = [ - { - name = "APCP"; - level = [ "A24" ]; - cat_thresh = [ >0.0, >=10.0 ]; - }, - { - name = "REFC"; - level = [ "L0" ]; - cat_thresh = [ >=35.0 ]; - GRIB1_ptv = 129; - }, - { - name = "UGRD"; - level = [ "Z10" ]; - cat_thresh = [ >=5.0 ]; - }, - { - name = "VGRD"; - level = [ "Z10" ]; - cat_thresh = [ >=5.0 ]; - }, - { - name = "WIND"; - level = [ "Z10" ]; - cat_thresh = [ >=5.0 ]; - } - ]; -} - // // IDs for ensemble members // Only set if processing a single file with all ensembles @@ -89,38 +44,11 @@ ens = { ens_member_ids = []; control_id = ""; -//////////////////////////////////////////////////////////////////////////////// - -// -// Neighborhood ensemble probabilities -// -nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; -} - -// -// NMEP smoothing methods -// -nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; -} - -//////////////////////////////////////////////////////////////////////////////// - // // May be set separately in each "fcst.field" and "obs.field" entry // +censor_thresh = []; +censor_val = []; prob_cat_thresh = []; // @@ -131,12 +59,15 @@ prob_pct_thresh = [ ==0.25 ]; // // May be set separately in each "obs.field" entry // +nc_var_str = ""; eclv_points = 0.05; // // Forecast and observation fields to be verified // fcst = { + ens_thresh = 1.0; + vld_thresh = 1.0; message_type = [ "ADPSFC" ]; field = [ @@ -315,23 +246,14 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types // ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = TRUE; - nmep = TRUE; - rank = TRUE; weight = FALSE; + rank = TRUE; + vld_count = TRUE; + mean = TRUE; } //////////////////////////////////////////////////////////////////////////////// From b4436e2bd526f239b378579d7490db9ea6ee01f4 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 21:32:40 -0600 Subject: [PATCH 16/23] Per #1908, ci-run-unit update some Ensemble-Stat docs. --- docs/Users_Guide/ensemble-stat.rst | 177 ++++------------------------- 1 file changed, 24 insertions(+), 153 deletions(-) diff --git a/docs/Users_Guide/ensemble-stat.rst b/docs/Users_Guide/ensemble-stat.rst index 6eb9f008d3..aac1166b7b 100644 --- a/docs/Users_Guide/ensemble-stat.rst +++ b/docs/Users_Guide/ensemble-stat.rst @@ -7,26 +7,13 @@ Ensemble-Stat Tool Introduction ============ -The Ensemble-Stat tool may be run to create simple ensemble forecasts (mean, probability, spread, etc) from a set of several forecast model files to be used by the MET statistics tools. If observations are also included, ensemble statistics such as rank histograms, probability integral transform histograms, spread/skill variance, relative position and continuous ranked probability score are produced. Climatological mean and standard deviation data may also be provided, and will be used as a reference forecast in several of the output statistics. Finally, observation error perturbations can be included prior to calculation of statistics. Details about and equations for the statistics produced for ensembles are given in :numref:`Appendix C, Section %s `. +The Ensemble-Stat tool verifies deterministic ensemble members against gridded and/or point observations. It computes ensemble statistics such as rank histograms, probability integral transform histograms, spread/skill variance, relative position and continuous ranked probability score. Climatological mean and standard deviation data may also be provided, and is used as a reference forecast in several of the output statistics. Finally, observation error perturbations can be included prior to calculation of statistics. Details about and equations for the statistics produced for ensembles are given in :numref:`Appendix C, Section %s `. -.. note:: This tool will be changing! The ensemble product generation step provided by Ensemble-Stat is now found within the :ref:`Gen-Ens-Prod Tool`. The Gen-Ens-Prod tool replaces and extends that functionality. Users are strongly encouraged to migrate ensemble product generation from Ensemble-Stat to Gen-Ens-Prod, as new features will only be added to Gen-Ens-Prod and the existing Ensemble-Stat functionality will be deprecated in a future version. +.. note:: Earlier versions of the Ensemble-Stat tool supported both ensemble product generation and ensemble verification. However, the ensemble product generation logic has moved to the :ref:`Gen-Ens-Prod Tool`, which replaces and extends that functionality. Ensemble product generation was removed from Ensemble-Stat in version 11.0.0. Scientific and statistical aspects ================================== -Ensemble forecasts derived from a set of deterministic ensemble members ------------------------------------------------------------------------ - -Ensemble forecasts are often created as a set of deterministic forecasts. The ensemble members are rarely used separately. Instead, they can be combined in various ways to produce a forecast. MET can combine the ensemble members into some type of summary forecast according to user specifications. Ensemble means are the most common, and can be paired with the ensemble variance or spread. Maximum, minimum and other summary values are also available, with details in the practical information section. - -Typically an ensemble is constructed by selecting a single forecast value from each member for each observation. When the High Resolution Assessment (HiRA) interpolation method is chosen, all of the nearby neighborhood points surrounding each observation from each member are used. Therefore, processing an N-member ensemble using a HiRA neighborhood of size M produces ensemble output with size N*M. This approach fully leverages information from all nearby grid points to evaluate the ensemble quality. - -The ensemble relative frequency is the simplest method for turning a set of deterministic forecasts into something resembling a probability forecast. For each categorical threshold (cat_thresh) listed for each field array entry of the ensemble dictionary (ens.field), MET will create the ensemble relative frequency as the proportion of ensemble members forecasting that event. For example, if 5 out of 10 ensemble members predict measurable precipitation at a grid location, then the ensemble relative frequency of precipitation will be :math:`5/10=0.5`. If the ensemble relative frequency is calibrated (unlikely) then this could be thought of as a probability of precipitation. - -The neighborhood ensemble probability (NEP) and neighborhood maximum ensemble probability (NMEP) methods are described in :ref:`Schwartz and Sobash (2017) `. They are an extension of the ensemble relative frequencies described above. The NEP value is computed by averaging the relative frequency of the event within the neighborhood over all ensemble members. The NMEP value is computed as the fraction of ensemble members for which the event is occurring somewhere within the surrounding neighborhood. The NMEP output is typically smoothed using a Gaussian kernel filter. The neighborhood sizes and smoothing options can be customized in the configuration file. - -The Ensemble-Stat tool writes the gridded relative frequencies, NEP, and NMEP fields to a NetCDF output file. Probabilistic verification methods can then be applied to those fields by evaluating them with the Grid-Stat and/or Point-Stat tools. - Ensemble statistics ------------------- @@ -168,33 +155,16 @@ ____________________ output_prefix = ""; version = "VN.N"; + The configuration options listed above are common to many MET tools and are described in :numref:`config_options`. Note that the **HIRA** interpolation method is only supported in Ensemble-Stat. _____________________ -.. code-block:: none - - ens = { - ens_thresh = 1.0; - vld_thresh = 1.0; - field = [ - { - name = "APCP"; - level = "A03"; - cat_thresh = [ >0.0, >=5.0 ]; - } - ]; - } - -The **ens** dictionary defines which ensemble fields should be processed. - -When summarizing the ensemble, compute a ratio of the number of valid ensemble fields to the total number of ensemble members. If this ratio is less than the **ens_thresh**, then quit with an error. This threshold must be between 0 and 1. Setting this threshold to 1 will require that all ensemble members be present to be processed. - - -When summarizing the ensemble, for each grid point compute a ratio of the number of valid data values to the number of ensemble members. If that ratio is less than **vld_thresh**, write out bad data. This threshold must be between 0 and 1. Setting this threshold to 1 will require each grid point to contain valid data for all ensemble members. +When processing the **fcst** data, compute a ratio of the number of valid ensemble fields to the total number of ensemble members. If this ratio is less than the **ens_thresh**, then quit with an error. This threshold must be between 0 and 1. Setting this threshold to 1 will require that all ensemble members be present to be processed. +When processing the **fcst** data, for each grid point compute a ratio of the number of valid data values to the number of ensemble members. If that ratio is less than **vld_thresh**, write out bad data. This threshold must be between 0 and 1. Setting this threshold to 1 will require each grid point to contain valid data for all ensemble members. For each **field** listed in the forecast field, give the name and vertical or accumulation level, plus one or more categorical thresholds. The thresholds are specified using symbols, as shown above. It is the user's responsibility to know the units for each model variable and to choose appropriate threshold values. The thresholds are used to define ensemble relative frequencies, e.g. a threshold of >=5 can be used to compute the proportion of ensemble members predicting precipitation of at least 5mm at each grid point. @@ -205,6 +175,7 @@ _______________________ ens_member_ids = []; control_id = ""; + The **ens_member_ids** array is only used if reading a single file that contains all ensemble members. It should contain a list of string identifiers that are substituted into the **ens** and/or **fcst** dictionary fields to determine which data to read from the file. @@ -215,7 +186,7 @@ Each value in the array will replace the text **MET_ENS_MEMBER_ID**. .. code-block:: none - ens = { + fcst = { field = [ { name = "fcst"; @@ -224,11 +195,12 @@ Each value in the array will replace the text **MET_ENS_MEMBER_ID**. ]; } + **GRIB Example:** .. code-block:: none - ens = { + fcst = { field = [ { name = "fcst"; @@ -238,52 +210,11 @@ Each value in the array will replace the text **MET_ENS_MEMBER_ID**. ]; } + **control_id** is a string that is substituted in the same way as the **ens_member_ids** values to read a control member. This value is only used when the **-ctrl** command line argument is used. The value should not be found in the **ens_member_ids** array. -_______________________ - -.. code-block:: none - - nbrhd_prob = { - width = [ 5 ]; - shape = CIRCLE; - vld_thresh = 0.0; - } - - -The **nbrhd_prob** dictionary defines the neighborhoods used to compute NEP and NMEP output. - - -The neighborhood **shape** is a **SQUARE** or **CIRCLE** centered on the current point, and the **width** array specifies the width of the square or diameter of the circle as an odd integer. The **vld_thresh** entry is a number between 0 and 1 specifying the required ratio of valid data in the neighborhood for an output value to be computed. - - -If **ensemble_flag.nep** is set to TRUE, NEP output is created for each combination of the categorical threshold (**cat_thresh**) and neighborhood width specified. - -_____________________ - -.. code-block:: none - - nmep_smooth = { - vld_thresh = 0.0; - shape = CIRCLE; - gaussian_dx = 81.27; - gaussian_radius = 120; - type = [ - { - method = GAUSSIAN; - width = 1; - } - ]; - } - - -Similar to the **interp** dictionary, the **nmep_smooth** dictionary includes a **type** array of dictionaries to define one or more methods for smoothing the NMEP data. Setting the interpolation method to nearest neighbor (**NEAREST**) effectively disables this smoothing step. - - -If **ensemble_flag.nmep** is set to TRUE, NMEP output is created for each combination of the categorical threshold (**cat_thresh**), neighborhood width (**nbrhd_prob.width**), and smoothing method(**nmep_smooth.type**) specified. - _____________________ .. code-block:: none @@ -334,6 +265,7 @@ The **prob_pct_thresh** entry is an array of thresholds which define the Nx2 pro prob_cat_thresh = [ ==0.25 ]; + __________________ .. code-block:: none @@ -386,7 +318,6 @@ _________________ The **output_flag** array controls the type of output that is generated. Each flag corresponds to an output line type in the STAT file. Setting the flag to NONE indicates that the line type should not be generated. Setting the flag to STAT indicates that the line type should be written to the STAT file only. Setting the flag to BOTH indicates that the line type should be written to the STAT file as well as a separate ASCII file where the data is grouped by line type. The output flags correspond to the following output line types: - 1. **ECNT** for Continuous Ensemble Statistics 2. **RPS** for Ranked Probability Score Statistics @@ -417,50 +348,24 @@ _____________________ ensemble_flag = { latlon = TRUE; - mean = TRUE; - stdev = TRUE; - minus = TRUE; - plus = TRUE; - min = TRUE; - max = TRUE; - range = TRUE; - vld_count = TRUE; - frequency = TRUE; - nep = FALSE; - nmep = FALSE; - rank = TRUE; - weight = FALSE; + weight = FALSE; + rank = TRUE; + vld_count = TRUE; + mean = TRUE; } -The **ensemble_flag** specifies which derived ensemble fields should be calculated and output. Setting the flag to TRUE produces output of the specified field, while FALSE produces no output for that field type. The flags correspond to the following output line types: - -1. Grid Latitude and Longitude Fields - -2. Ensemble Mean Field - -3. Ensemble Standard Deviation Field - -4. Ensemble Mean - One Standard Deviation Field - -5. Ensemble Mean + One Standard Deviation Field -6. Ensemble Minimum Field +The **ensemble_flag** specifies which gridded verification output types should be written to the Observation Rank (**_orank.nc**) NetCDF file. Setting the flag to TRUE produces output of the specified field, while FALSE produces no output for that field type. The flags correspond to the following output line types: -7. Ensemble Maximum Field - -8. Ensemble Range Field - -9. Ensemble Valid Data Count - -10. Ensemble Relative Frequency for each categorical threshold (**cat_thresh**) specified. This is an uncalibrated probability forecast. +1. Grid Latitude and Longitude Fields -11. Neighborhood Ensemble Probability for each categorical threshold (**cat_thresh**) and neighborhood width (**nbrhd_prob.width**) specified. +2. The grid area weights. -12. Neighborhood Maximum Ensemble Probability for each categorical threshold (**cat_thresh**), neighborhood width (**nbrhd_prob.width**), and smoothing method (**nmep_smooth.type**) specified. +3. Observation values, ranks, and probability-integral transform values. -13. Observation Ranks for input gridded observations are written to a separate NetCDF output file. +4. Ensemble Valid Data Count -14. The grid area weights applied are written to the Observation Rank output file. +5. Ensemble Mean Field __________________ @@ -508,46 +413,12 @@ The output ASCII files are named similarly: ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of ecnt, rps, rhist, phist, relp, orank, and ssvar to indicate the line type it contains. -When fields are requested in the ens dictionary of the configuration file or verification against gridded fields is performed, ensemble_stat can produce output NetCDF files using the following naming convention: - - -ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.nc where TYPE is either ens or orank. The orank NetCDF output file contains gridded fields of observation ranks when the -grid_obs command line option is used. The ens NetCDF output file contains ensemble products derived from the fields requested in the ens dictionary of the configuration file. The Ensemble-Stat tool can calculate any of the following fields from the input ensemble members, as specified in the ensemble_flag dictionary in the configuration file: - - -Ensemble Mean fields - - -Ensemble Standard Deviation fields - - -Ensemble Mean - 1 Standard Deviation fields - - -Ensemble Mean + 1 Standard Deviation fields - - -Ensemble Minimum fields - - -Ensemble Maximum fields - - -Ensemble Range fields - - -Ensemble Valid Data Count fields - - -Ensemble Relative Frequency by threshold fields (e.g. ensemble probabilities) - - -Neighborhood Ensemble Probability and Neighborhood Maximum Ensemble Probability - +When verification against gridded analyses is performed, Ensemble-Stat can produce output NetCDF files using the following naming convention: -Rank for each Observation Value (if gridded observation field provided) +ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_orank.nc contains gridded fields of observation ranks when the -grid_obs command line option is used. Its contents are specified by the **ensemble_flag** configuration option. -When gridded or point observations are provided, using the -grid_obs and -point_obs command line options, respectively, the Ensemble-Stat tool can compute the following statistics for the fields specified in the fcst and obs dictionaries of the configuration file: +The Ensemble-Stat tool can compute the following statistics for the fields specified in the fcst and obs dictionaries of the configuration file: Continuous Ensemble Statistics From ba8b0c5a51f8a46c4c6565f33c8fd525f14acf92 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 22:30:16 -0600 Subject: [PATCH 17/23] Per #1908, ci-run-unit fix typo in config file and fix logic so that when we tack the control file to the end of the list of ensemble files, we also increment the n_ens_files counter. --- internal/test_unit/config/EnsembleStatConfig_grid_weight | 2 +- src/tools/core/ensemble_stat/ensemble_stat.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/internal/test_unit/config/EnsembleStatConfig_grid_weight b/internal/test_unit/config/EnsembleStatConfig_grid_weight index 52b15aec83..fcefb3dd04 100644 --- a/internal/test_unit/config/EnsembleStatConfig_grid_weight +++ b/internal/test_unit/config/EnsembleStatConfig_grid_weight @@ -215,7 +215,7 @@ ensemble_flag = { latlon = TRUE; weight = TRUE; rank = FALSE; - vld_count = FLASE; + vld_count = FALSE; mean = TRUE; } diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 3f00e5fe19..257f039ae2 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -312,6 +312,7 @@ void process_command_line(int argc, char **argv) { // Add control member file to end of the forecast file list ens_file_list.add(ctrl_file.c_str()); ctrl_file_index = ens_file_list.n()-1; + n_ens_files++; } // Check that the end_ut >= beg_ut From 660effed0e9efce125744f197f78749438721dd0 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Sun, 18 Sep 2022 23:23:53 -0600 Subject: [PATCH 18/23] Per #1908, ci-run-unit fix logic in ensemble_stat to make the TEST: ensemble_stat_SINGLE_FILE_NC_WITH_CTRL run. When all members are read from the same input file, DO NOT append the control file to the of the ensemble file list. --- src/tools/core/ensemble_stat/ensemble_stat.cc | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 257f039ae2..790d52349c 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -302,17 +302,29 @@ void process_command_line(int argc, char **argv) { // Append the control member, if specified if(ctrl_file.nonempty()) { - if(ens_file_list.has(ctrl_file) && n_ens_files != 1) { + if(n_ens_files == 1 && !ens_file_list.has(ctrl_file)) { + mlog << Error << "\nprocess_command_line() -> " + << "when reading all ensemble members from the same file, " + << "the control member must be in that file as well: " + << ctrl_file << "\n\n"; + exit(1); + } + else if(n_ens_files > 1 && ens_file_list.has(ctrl_file)) { mlog << Error << "\nprocess_command_line() -> " << "the ensemble control file should not appear in the list " - << "of ensemble member files:\n" << ctrl_file << "\n\n"; + << "of ensemble member files: " << ctrl_file << "\n\n"; exit(1); } - // Add control member file to end of the forecast file list - ens_file_list.add(ctrl_file.c_str()); - ctrl_file_index = ens_file_list.n()-1; - n_ens_files++; + // Store control member file information + if(n_ens_files == 1) { + ctrl_file_index = 0; + } + else { + ens_file_list.add(ctrl_file.c_str()); + n_ens_files++; + ctrl_file_index = ens_file_list.n()-1; + } } // Check that the end_ut >= beg_ut From 7254cdc3b94725ecc38afa495824bbe6cf6a51fd Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Mon, 19 Sep 2022 16:53:30 -0600 Subject: [PATCH 19/23] Per #1908, ci-run-unit more changes to Ensemble-Stat. Rename ensemble_flag to nc_orank_flag and update its contents. Also make it configurable separetly for each vx task. Also update the User's Guide with this info. --- data/config/EnsembleStatConfig_default | 10 +- docs/Users_Guide/ensemble-stat.rst | 28 ++-- internal/test_unit/config/EnsembleStatConfig | 10 +- .../config/EnsembleStatConfig_MASK_SID | 10 +- .../test_unit/config/EnsembleStatConfig_climo | 10 +- .../config/EnsembleStatConfig_grid_weight | 10 +- .../config/EnsembleStatConfig_one_cdf_bin | 6 +- .../config/EnsembleStatConfig_python | 10 +- .../config/EnsembleStatConfig_qty_inc_exc | 10 +- .../EnsembleStatConfig_single_file_grib | 10 +- .../config/EnsembleStatConfig_single_file_nc | 10 +- scripts/config/EnsembleStatConfig | 10 +- src/basic/vx_config/config_constants.h | 4 +- src/tools/core/ensemble_stat/ensemble_stat.cc | 45 +++--- src/tools/core/ensemble_stat/ensemble_stat.h | 9 +- .../ensemble_stat/ensemble_stat_conf_info.cc | 134 ++++++++++-------- .../ensemble_stat/ensemble_stat_conf_info.h | 14 +- 17 files changed, 207 insertions(+), 133 deletions(-) diff --git a/data/config/EnsembleStatConfig_default b/data/config/EnsembleStatConfig_default index 02d5a3f4fb..04bf1fd6ee 100644 --- a/data/config/EnsembleStatConfig_default +++ b/data/config/EnsembleStatConfig_default @@ -215,6 +215,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = NONE; @@ -235,13 +236,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/docs/Users_Guide/ensemble-stat.rst b/docs/Users_Guide/ensemble-stat.rst index aac1166b7b..2036ab4457 100644 --- a/docs/Users_Guide/ensemble-stat.rst +++ b/docs/Users_Guide/ensemble-stat.rst @@ -345,27 +345,33 @@ The **output_flag** array controls the type of output that is generated. Each fl _____________________ .. code-block:: none - - ensemble_flag = { + + nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } -The **ensemble_flag** specifies which gridded verification output types should be written to the Observation Rank (**_orank.nc**) NetCDF file. Setting the flag to TRUE produces output of the specified field, while FALSE produces no output for that field type. The flags correspond to the following output line types: +The **nc_orank_flag** specifies which gridded verification output types should be written to the Observation Rank (**_orank.nc**) NetCDF file. This output file is only created when gridded observations have been provided with the -grid_obs command line option. Setting the flag to TRUE produces output of the specified field, while FALSE produces no output for that field type. The flags correspond to the following output line types: 1. Grid Latitude and Longitude Fields -2. The grid area weights. +2. Ensemble mean field + +3. Raw observation values + +4. Observation ranks -3. Observation values, ranks, and probability-integral transform values. +5. Observation probability-integral transform values -4. Ensemble Valid Data Count +6. Ensemble valid data count -5. Ensemble Mean Field +7. Grid area weight values __________________ @@ -410,13 +416,13 @@ ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV.stat where PREFIX indicates the user-defin The output ASCII files are named similarly: -ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of ecnt, rps, rhist, phist, relp, orank, and ssvar to indicate the line type it contains. +ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_TYPE.txt where TYPE is one of elements of the **output_flag** configuration option to indicate the line type it contains. When verification against gridded analyses is performed, Ensemble-Stat can produce output NetCDF files using the following naming convention: -ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_orank.nc contains gridded fields of observation ranks when the -grid_obs command line option is used. Its contents are specified by the **ensemble_flag** configuration option. +ensemble_stat_PREFIX_YYYYMMDD_HHMMSSV_orank.nc contains gridded fields of observation ranks when the -grid_obs command line option is used. Its contents are specified by the **nc_orank_flag** configuration option. The Ensemble-Stat tool can compute the following statistics for the fields specified in the fcst and obs dictionaries of the configuration file: diff --git a/internal/test_unit/config/EnsembleStatConfig b/internal/test_unit/config/EnsembleStatConfig index cc5626c6a7..4922db14e4 100644 --- a/internal/test_unit/config/EnsembleStatConfig +++ b/internal/test_unit/config/EnsembleStatConfig @@ -181,6 +181,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -201,13 +202,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_MASK_SID b/internal/test_unit/config/EnsembleStatConfig_MASK_SID index 356fdb3ec4..38a9174064 100644 --- a/internal/test_unit/config/EnsembleStatConfig_MASK_SID +++ b/internal/test_unit/config/EnsembleStatConfig_MASK_SID @@ -173,6 +173,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -193,13 +194,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = FALSE; rank = FALSE; + pit = FALSE; vld_count = FALSE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_climo b/internal/test_unit/config/EnsembleStatConfig_climo index 0e693e23c8..3b118c06ec 100644 --- a/internal/test_unit/config/EnsembleStatConfig_climo +++ b/internal/test_unit/config/EnsembleStatConfig_climo @@ -202,6 +202,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -222,13 +223,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = FALSE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = FALSE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_grid_weight b/internal/test_unit/config/EnsembleStatConfig_grid_weight index fcefb3dd04..bb07dbca49 100644 --- a/internal/test_unit/config/EnsembleStatConfig_grid_weight +++ b/internal/test_unit/config/EnsembleStatConfig_grid_weight @@ -190,6 +190,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -210,13 +211,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = TRUE; + mean = TRUE; + raw = FALSE; rank = FALSE; + pit = FALSE; vld_count = FALSE; - mean = TRUE; + weight = TRUE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin b/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin index a2036bf6e6..9a638d89cd 100644 --- a/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin +++ b/internal/test_unit/config/EnsembleStatConfig_one_cdf_bin @@ -195,6 +195,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -214,9 +215,10 @@ output_flag = { //////////////////////////////////////////////////////////////////////////////// // -// Ensemble product output types +// Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = false; +nc_orank_flag = false; //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_python b/internal/test_unit/config/EnsembleStatConfig_python index 61bb4056b7..734479b93d 100644 --- a/internal/test_unit/config/EnsembleStatConfig_python +++ b/internal/test_unit/config/EnsembleStatConfig_python @@ -177,6 +177,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -197,13 +198,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = FALSE; rank = FALSE; + pit = FALSE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc b/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc index 44cd84fb69..5fd29fce6f 100644 --- a/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc +++ b/internal/test_unit/config/EnsembleStatConfig_qty_inc_exc @@ -190,6 +190,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -210,13 +211,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_single_file_grib b/internal/test_unit/config/EnsembleStatConfig_single_file_grib index e6a0dfa7bd..fa9430c1d6 100644 --- a/internal/test_unit/config/EnsembleStatConfig_single_file_grib +++ b/internal/test_unit/config/EnsembleStatConfig_single_file_grib @@ -226,6 +226,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -246,13 +247,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/internal/test_unit/config/EnsembleStatConfig_single_file_nc b/internal/test_unit/config/EnsembleStatConfig_single_file_nc index 40c35ebc48..bcf58eb3cb 100644 --- a/internal/test_unit/config/EnsembleStatConfig_single_file_nc +++ b/internal/test_unit/config/EnsembleStatConfig_single_file_nc @@ -232,6 +232,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = STAT; @@ -252,13 +253,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/scripts/config/EnsembleStatConfig b/scripts/config/EnsembleStatConfig index f59e21ef9f..d973d2f113 100644 --- a/scripts/config/EnsembleStatConfig +++ b/scripts/config/EnsembleStatConfig @@ -227,6 +227,7 @@ interp = { // // Statistical output types +// May be set separately in each "obs.field" entry // output_flag = { ecnt = BOTH; @@ -247,13 +248,16 @@ output_flag = { // // Gridded verification output types +// May be set separately in each "obs.field" entry // -ensemble_flag = { +nc_orank_flag = { latlon = TRUE; - weight = FALSE; + mean = TRUE; + raw = TRUE; rank = TRUE; + pit = TRUE; vld_count = TRUE; - mean = TRUE; + weight = FALSE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/basic/vx_config/config_constants.h b/src/basic/vx_config/config_constants.h index d23d4bf724..5cb03579d4 100644 --- a/src/basic/vx_config/config_constants.h +++ b/src/basic/vx_config/config_constants.h @@ -739,8 +739,9 @@ static const char conf_key_nmep_smooth[] = "nmep_smooth"; static const char conf_key_skip_const[] = "skip_const"; static const char conf_key_rng_type[] = "rng.type"; static const char conf_key_rng_seed[] = "rng.seed"; -static const char conf_key_ensemble_flag[] = "ensemble_flag"; +static const char conf_key_nc_orank_flag[] = "nc_orank_flag"; static const char conf_key_rank_flag[] = "rank"; +static const char conf_key_pit_flag[] = "pit"; static const char conf_key_ssvar_bin[] = "ens_ssvar_bin_size"; static const char conf_key_phist_bin[] = "ens_phist_bin_size"; static const char conf_key_prob_cat_thresh[] = "prob_cat_thresh"; @@ -760,6 +761,7 @@ static const char conf_key_ens_field[] = "ens.field"; static const char conf_key_ens_ens_thresh[] = "ens.ens_thresh"; static const char conf_key_ens_vld_thresh[] = "ens.vld_thresh"; static const char conf_key_normalize[] = "normalize"; +static const char conf_key_ensemble_flag[] = "ensemble_flag"; static const char conf_key_mean_flag[] = "mean"; static const char conf_key_stdev_flag[] = "stdev"; static const char conf_key_minus_flag[] = "minus"; diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index 790d52349c..6d3309289e 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -411,6 +411,9 @@ void process_command_line(int argc, char **argv) { conf_info.process_config(etype, otype, grid_obs_flag, point_obs_flag, use_var_id, &ens_file_list, ctrl_file.nonempty()); + // Set output_nc_flag + out_nc_flag = (grid_obs_flag && !conf_info.nc_info.all_false()); + // Set the model name shc.set_model(conf_info.model.c_str()); @@ -1383,7 +1386,7 @@ void process_grid_vx() { // If requested in the config file, create a NetCDF file to store // the verification matched pairs - if(!conf_info.nc_info.all_false() && nc_out == (NcFile *) 0) { + if(out_nc_flag && nc_out == (NcFile *) 0) { setup_nc_file(fcst_dp[j].valid(), "_orank.nc"); } @@ -1556,9 +1559,7 @@ void process_grid_vx() { pd_all.compute_pair_vals(conf_info.rng_ptr); // Write NetCDF output - if(!conf_info.nc_info.all_false()) { - write_orank_nc(pd_all, obs_dp, i, j, k); - } + if(out_nc_flag) write_orank_nc(pd_all, obs_dp, i, j, k); // Write the stat output write_txt_files(conf_info.vx_opt[i], pd_all, false); @@ -1737,7 +1738,6 @@ void do_rps(const EnsembleStatVxOpt &vx_opt, //////////////////////////////////////////////////////////////////////// void setup_nc_file(unixtime valid_ut, const char *suffix) { - ConcatString out_nc_file; // Create output NetCDF file name build_outfile_name(ens_valid_ut, suffix, out_nc_file); @@ -1770,9 +1770,6 @@ void setup_nc_file(unixtime valid_ut, const char *suffix) { conf_info.grid_weight_flag, wgt_dp); } - // Append to the list of output files - out_nc_file_list.add(out_nc_file); - return; } @@ -2493,18 +2490,29 @@ void write_orank_nc(PairDataEnsemble &pd, DataPlane &dp, } // end for i - // Add the observation values and ranks - if(conf_info.nc_info.do_orank) { + // Add the ensemble mean values + if(conf_info.nc_info.do_mean) { + write_orank_var_float(i_vx, i_interp, i_mask, ens_mean, dp, + "ENS_MEAN", + "Ensemble Mean"); + } + + // Add the observation values + if(conf_info.nc_info.do_raw) { write_orank_var_float(i_vx, i_interp, i_mask, obs_v, dp, "OBS", "Observation Value"); + } - // Add the observation ranks + // Add the observation ranks + if(conf_info.nc_info.do_rank) { write_orank_var_int(i_vx, i_interp, i_mask, obs_rank, dp, "OBS_RANK", "Observation Rank"); + } - // Add the probability integral transforms + // Add the probability integral transforms + if(conf_info.nc_info.do_pit) { write_orank_var_float(i_vx, i_interp, i_mask, obs_pit, dp, "OBS_PIT", "Probability Integral Transform"); @@ -2517,13 +2525,6 @@ void write_orank_nc(PairDataEnsemble &pd, DataPlane &dp, "Ensemble Valid Data Count"); } - // Add the ensemble mean values - if(conf_info.nc_info.do_mean) { - write_orank_var_float(i_vx, i_interp, i_mask, ens_mean, dp, - "ENS_MEAN", - "Ensemble Mean"); - } - // Deallocate and clean up if(obs_v) { delete [] obs_v; obs_v = (float *) 0; } if(obs_rank) { delete [] obs_rank; obs_rank = (int *) 0; } @@ -2730,10 +2731,10 @@ void clean_up() { // Close the output text files that were open for writing finish_txt_files(); - // List the output NetCDF files - for(i=0; i " - << "lookup failed for key \"" << conf_key_ensemble_flag - << "\"\n\n"; - exit(1); - } - - const ConfigObjectType type = e->type(); - - if(type == BooleanType) { - bool value = e->b_value(); - - if(!value) nc_info.set_all_false(); - - return; - } - - // It should be a dictionary - if(type != DictionaryType) { - mlog << Error - << "\nEnsembleStatConfInfo::parse_nc_info() -> " - << "bad type (" << configobjecttype_to_string(type) - << ") for key \"" << conf_key_ensemble_flag << "\"\n\n"; - exit(1); - } - - // Parse the various entries - Dictionary * d = e->dict_value(); - - nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); - nc_info.do_weight = d->lookup_bool(conf_key_weight); - nc_info.do_orank = d->lookup_bool(conf_key_rank_flag); - nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); - nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); - - return; -} - -//////////////////////////////////////////////////////////////////////// - void EnsembleStatConfInfo::process_flags() { int i, j; bool output_ascii_flag = false; // Initialize for(i=0; i " + << "lookup failed for key \"" << conf_key_nc_orank_flag + << "\"\n\n"; + exit(1); + } + + const ConfigObjectType type = e->type(); + + if(type == BooleanType) { + bool value = e->b_value(); + + if(!value) nc_info.set_all_false(); + + return; + } + + // It should be a dictionary + if(type != DictionaryType) { + mlog << Error + << "\nEnsembleStatVxOpt::parse_nc_info() -> " + << "bad type (" << configobjecttype_to_string(type) + << ") for key \"" << conf_key_nc_orank_flag << "\"\n\n"; + exit(1); + } + + // Parse the various entries + Dictionary * d = e->dict_value(); + + nc_info.do_latlon = d->lookup_bool(conf_key_latlon_flag); + nc_info.do_mean = d->lookup_bool(conf_key_mean_flag); + nc_info.do_raw = d->lookup_bool(conf_key_raw_flag); + nc_info.do_rank = d->lookup_bool(conf_key_rank_flag); + nc_info.do_pit = d->lookup_bool(conf_key_pit_flag); + nc_info.do_vld = d->lookup_bool(conf_key_vld_count_flag); + nc_info.do_weight = d->lookup_bool(conf_key_weight); + + return; +} + +//////////////////////////////////////////////////////////////////////// + void EnsembleStatVxOpt::set_vx_pd(EnsembleStatConfInfo *conf_info, int ctrl_index) { int i, j, n; int n_msg_typ = msg_typ.n(); @@ -1146,8 +1162,9 @@ void EnsembleStatNcOutInfo::clear() { bool EnsembleStatNcOutInfo::all_false() const { - bool status = do_latlon || do_weight || do_rank || - do_vld || do_mean; + bool status = do_latlon || do_mean || do_raw || + do_rank || do_pit || do_vld || + do_weight; return(!status); } @@ -1157,24 +1174,27 @@ bool EnsembleStatNcOutInfo::all_false() const { void EnsembleStatNcOutInfo::set_all_false() { do_latlon = false; - do_weight = false; - do_orank = false; - do_vld = false; do_mean = false; + do_raw = false; + do_rank = false; + do_pit = false; + do_vld = false; + do_weight = false; return; } - //////////////////////////////////////////////////////////////////////// void EnsembleStatNcOutInfo::set_all_true() { do_latlon = true; - do_weight = true; - do_orank = true; - do_vld = true; do_mean = true; + do_raw = true; + do_rank = true; + do_pit = true; + do_vld = true; + do_weight = true; return; } diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h index e90828a583..a011b89fe4 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.h @@ -53,10 +53,12 @@ static const STATLineType txt_file_type[n_txt] = { struct EnsembleStatNcOutInfo { bool do_latlon; - bool do_weight; - bool do_orank; - bool do_vld; bool do_mean; + bool do_raw; + bool do_rank; + bool do_pit; + bool do_vld; + bool do_weight; ////////////////////////////////////////////////////////////////// @@ -134,6 +136,7 @@ class EnsembleStatVxOpt { // Output file options STATOutputType output_flag[n_txt]; // Flag for each output line type + EnsembleStatNcOutInfo nc_info; // Output NetCDF pairs file contents ////////////////////////////////////////////////////////////////// @@ -144,6 +147,7 @@ class EnsembleStatVxOpt { gsl_rng *, bool, bool, bool, StringArray, StringArray *, bool, ConcatString); + void parse_nc_info(Dictionary &); void set_vx_pd(EnsembleStatConfInfo *, int); void set_perc_thresh(const PairDataEnsemble *); @@ -231,8 +235,7 @@ class EnsembleStatConfInfo { ConcatString version; // Config file version STATOutputType output_flag[n_txt]; // Summary of output_flag options - - EnsembleStatNcOutInfo nc_info; // Output NetCDF file contents + EnsembleStatNcOutInfo nc_info; // Summary of output NetCDF file contents ////////////////////////////////////////////////////////////////// @@ -242,7 +245,6 @@ class EnsembleStatConfInfo { void process_config(GrdFileType, GrdFileType, bool, bool, bool, StringArray *, bool); void process_flags (); - void parse_nc_info (); void process_masks (const Grid &); void set_vx_pd (const IntArray &, int); From ea629c2c129e4c5ab169492cd770be2f855e1679 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Tue, 20 Sep 2022 10:01:32 -0600 Subject: [PATCH 20/23] Per #1908, update the list of expected _orank.nc files from ensemble_stat runs. Needed to add 3 that are now being created. --- internal/test_unit/xml/unit_grid_weight.xml | 3 +++ internal/test_unit/xml/unit_python.xml | 1 + 2 files changed, 4 insertions(+) diff --git a/internal/test_unit/xml/unit_grid_weight.xml b/internal/test_unit/xml/unit_grid_weight.xml index ebf0b03bc5..85005feec1 100644 --- a/internal/test_unit/xml/unit_grid_weight.xml +++ b/internal/test_unit/xml/unit_grid_weight.xml @@ -96,6 +96,7 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V.stat + &OUTPUT_DIR;/grid_weight/ensemble_stat_NO_WEIGHT_20120410_120000V_orank.nc @@ -120,6 +121,7 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V.stat + &OUTPUT_DIR;/grid_weight/ensemble_stat_COS_LAT_WEIGHT_20120410_120000V_orank.nc @@ -144,6 +146,7 @@ &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V.stat + &OUTPUT_DIR;/grid_weight/ensemble_stat_AREA_WEIGHT_20120410_120000V_orank.nc diff --git a/internal/test_unit/xml/unit_python.xml b/internal/test_unit/xml/unit_python.xml index 9f1b785a36..94dfac5e68 100644 --- a/internal/test_unit/xml/unit_python.xml +++ b/internal/test_unit/xml/unit_python.xml @@ -361,6 +361,7 @@ &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V.stat + &OUTPUT_DIR;/python/ensemble_stat_PYTHON_20050807_120000V_orank.nc From a8a5a4e7eeadd19c7ad5b85d31930406cc9be3fe Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Tue, 20 Sep 2022 16:26:40 -0600 Subject: [PATCH 21/23] Per #1908, add more error checking to CNTInfo::compute_ci(). Compute compute normal ci's when the forecast, observation, and error standard deviations are bad data. --- src/libcode/vx_statistics/met_stats.cc | 124 +++++++++++++++---------- 1 file changed, 76 insertions(+), 48 deletions(-) diff --git a/src/libcode/vx_statistics/met_stats.cc b/src/libcode/vx_statistics/met_stats.cc index cd1443fac6..15c69df188 100644 --- a/src/libcode/vx_statistics/met_stats.cc +++ b/src/libcode/vx_statistics/met_stats.cc @@ -915,50 +915,69 @@ void CNTInfo::compute_ci() { cv_chi2_u = chi2_cdf_inv(1.0 - (alpha[i]/2.0), n-1); // - // Compute confidence interval for forecast mean using VIF + // Check for bad data // - v = fbar.vif*fstdev.v*fstdev.v; - fbar.v_ncl[i] = fbar.v + cv_normal_l*sqrt(v)/sqrt((double) n); - fbar.v_ncu[i] = fbar.v + cv_normal_u*sqrt(v)/sqrt((double) n); - - // - // Compute confidence interval for forecast standard deviation, - // assuming normality of the forecast values - // - v = (n-1)*fstdev.v*fstdev.v/cv_chi2_u; - if(v < 0) fstdev.v_ncl[i] = bad_data_double; - else fstdev.v_ncl[i] = sqrt(v); - - v = (n-1)*fstdev.v*fstdev.v/cv_chi2_l; - if(v < 0) fstdev.v_ncu[i] = bad_data_double; - else fstdev.v_ncu[i] = sqrt(v); + if(is_bad_data(fstdev.v)) { + fbar.v_ncl[i] = fbar.v_ncu[i] = bad_data_double; + fstdev.v_ncl[i] = fstdev.v_ncu[i] = bad_data_double; + } + else { - // - // Compute confidence interval for observation mean using VIF - // - v = obar.vif*ostdev.v*ostdev.v; - obar.v_ncl[i] = obar.v + cv_normal_l*sqrt(v)/sqrt((double) n); - obar.v_ncu[i] = obar.v + cv_normal_u*sqrt(v)/sqrt((double) n); + // + // Compute confidence interval for forecast mean using VIF + // + v = fbar.vif*fstdev.v*fstdev.v; + fbar.v_ncl[i] = fbar.v + cv_normal_l*sqrt(v)/sqrt((double) n); + fbar.v_ncu[i] = fbar.v + cv_normal_u*sqrt(v)/sqrt((double) n); + + // + // Compute confidence interval for forecast standard deviation, + // assuming normality of the forecast values + // + v = (n-1)*fstdev.v*fstdev.v/cv_chi2_u; + if(v < 0) fstdev.v_ncl[i] = bad_data_double; + else fstdev.v_ncl[i] = sqrt(v); + + v = (n-1)*fstdev.v*fstdev.v/cv_chi2_l; + if(v < 0) fstdev.v_ncu[i] = bad_data_double; + else fstdev.v_ncu[i] = sqrt(v); + } // - // Compute confidence interval for observation standard deviation - // assuming normality of the observation values + // Check for bad data // - v = (n-1)*ostdev.v*ostdev.v/cv_chi2_u; - if(v < 0) ostdev.v_ncl[i] = bad_data_double; - else ostdev.v_ncl[i] = sqrt(v); + if(is_bad_data(ostdev.v)) { + obar.v_ncl[i] = obar.v_ncu[i] = bad_data_double; + ostdev.v_ncl[i] = ostdev.v_ncu[i] = bad_data_double; + } + else { - v = (n-1)*ostdev.v*ostdev.v/cv_chi2_l; - if(v < 0) ostdev.v_ncu[i] = bad_data_double; - else ostdev.v_ncu[i] = sqrt(v); + // + // Compute confidence interval for observation mean using VIF + // + v = obar.vif*ostdev.v*ostdev.v; + obar.v_ncl[i] = obar.v + cv_normal_l*sqrt(v)/sqrt((double) n); + obar.v_ncu[i] = obar.v + cv_normal_u*sqrt(v)/sqrt((double) n); + + // + // Compute confidence interval for observation standard deviation + // assuming normality of the observation values + // + v = (n-1)*ostdev.v*ostdev.v/cv_chi2_u; + if(v < 0) ostdev.v_ncl[i] = bad_data_double; + else ostdev.v_ncl[i] = sqrt(v); + + v = (n-1)*ostdev.v*ostdev.v/cv_chi2_l; + if(v < 0) ostdev.v_ncu[i] = bad_data_double; + else ostdev.v_ncu[i] = sqrt(v); + } // // Compute confidence interval for the pearson correlation coefficient // if(is_bad_data(pr_corr.v) || n <= 3 || is_eq(pr_corr.v, 1.0) || is_eq(pr_corr.v, -1.0)) { - pr_corr.v_ncl[i] = bad_data_double; - pr_corr.v_ncu[i] = bad_data_double; + pr_corr.v_ncl[i] = pr_corr.v_ncu[i] = bad_data_double; } else { v = 0.5*log((1 + pr_corr.v)/(1 - pr_corr.v)); @@ -973,8 +992,7 @@ void CNTInfo::compute_ci() { // if(is_bad_data(anom_corr.v) || n <= 3 || is_eq(anom_corr.v, 1.0) || is_eq(anom_corr.v, -1.0)) { - anom_corr.v_ncl[i] = bad_data_double; - anom_corr.v_ncu[i] = bad_data_double; + anom_corr.v_ncl[i] = anom_corr.v_ncu[i] = bad_data_double; } else { v = 0.5*log((1 + anom_corr.v)/(1 - anom_corr.v)); @@ -985,22 +1003,32 @@ void CNTInfo::compute_ci() { } // - // Compute confidence interval for mean error using VIF - // - v = me.vif*estdev.v*estdev.v; - me.v_ncl[i] = me.v + cv_normal_l*sqrt(v)/sqrt((double) n); - me.v_ncu[i] = me.v + cv_normal_u*sqrt(v)/sqrt((double) n); - + // Check for bad data // - // Compute confidence interval for the error standard deviation - // - v = (n-1)*estdev.v*estdev.v/cv_chi2_u; - if(v < 0) estdev.v_ncl[i] = bad_data_double; - else estdev.v_ncl[i] = sqrt(v); + if(is_bad_data(estdev.v)) { + me.v_ncl[i] = me.v_ncu[i] = bad_data_double; + estdev.v_ncl[i] = estdev.v_ncu[i] = bad_data_double; + } + else { - v = (n-1)*estdev.v*estdev.v/cv_chi2_l; - if(v < 0) estdev.v_ncu[i] = bad_data_double; - else estdev.v_ncu[i] = sqrt(v); + // + // Compute confidence interval for mean error using VIF + // + v = me.vif*estdev.v*estdev.v; + me.v_ncl[i] = me.v + cv_normal_l*sqrt(v)/sqrt((double) n); + me.v_ncu[i] = me.v + cv_normal_u*sqrt(v)/sqrt((double) n); + + // + // Compute confidence interval for the error standard deviation + // + v = (n-1)*estdev.v*estdev.v/cv_chi2_u; + if(v < 0) estdev.v_ncl[i] = bad_data_double; + else estdev.v_ncl[i] = sqrt(v); + + v = (n-1)*estdev.v*estdev.v/cv_chi2_l; + if(v < 0) estdev.v_ncu[i] = bad_data_double; + else estdev.v_ncu[i] = sqrt(v); + } } // end for i From 8d3e524716c3bb1b40c0fa5108d8846e64a0f674 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Tue, 20 Sep 2022 16:28:04 -0600 Subject: [PATCH 22/23] Per #1908, remove unneeded debug comment. --- src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc index 4b9f08bbde..29e32e881e 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -176,8 +176,6 @@ void EnsembleStatConfInfo::process_config(GrdFileType etype, msg_typ_sfc = msg_typ_group_map[(string)surface_msg_typ_group_str]; } -// JHG summarize the nc_infos? - // Conf: ens_member_ids ens_member_ids = parse_conf_ens_member_ids(&conf); From 4225d4008aa82b7407c87f031973153812a91657 Mon Sep 17 00:00:00 2001 From: John Halley Gotway Date: Tue, 20 Sep 2022 16:46:20 -0600 Subject: [PATCH 23/23] Unrelated to #1908, update airnow handler in ascii2nc to write bad data as bad_data_double (-9999) instead of -999. --- src/tools/other/ascii2nc/aeronet_handler.cc | 9 ++++---- src/tools/other/ascii2nc/airnow_handler.cc | 24 ++++++++------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/tools/other/ascii2nc/aeronet_handler.cc b/src/tools/other/ascii2nc/aeronet_handler.cc index 0c9bf2ad7a..7cdc07d7d0 100644 --- a/src/tools/other/ascii2nc/aeronet_handler.cc +++ b/src/tools/other/ascii2nc/aeronet_handler.cc @@ -47,7 +47,7 @@ const string lat_col2 = "Latitude"; // "Latitude(degrees)" const string lon_col2 = "Longitude"; // "Longitude(degrees)" const string elv_col2 = "Elevation"; // "Elevation(meters)" -const string AeronetHandler::HEADER_TYPE = ""; ///// +const string AeronetHandler::HEADER_TYPE = ""; const int AeronetHandler::AOT_GRIB_CODE = 129; // Version 2 @@ -68,8 +68,6 @@ const string WAVELENGTHS_INPUT_AOD_NAME = "Exact_Wavelengths_for_Input_AOD"; static int format_version; -const float AERONET_MISSING_VALUE = -999.; - double angstrom_power_interplation(double value_1, double value_2, double level_1, double level_2, double target_level); @@ -416,7 +414,6 @@ bool AeronetHandler::_readObservations(LineDataFile &ascii_file) var_id = header_var_index[k]; var_name = header_var_names[k]; dheight = header_heights[k]; - //if (is_eq(atof(data_line[k]), AERONET_MISSING_VALUE)) continue; if (strcmp(var_name.c_str(), AOD_NAME.c_str()) == 0) { if (is_eq(dheight, 550)) has_aod_at_550 = true; else if (is_eq(dheight, 440)) aod_at_440 = atof(data_line[k]); @@ -768,9 +765,13 @@ string AeronetHandler::make_var_name_from_header(string hdr_field) { return var_name; } +//////////////////////////////////////////////////////////////////////// + double angstrom_power_interplation(double value_1, double value_2, double level_1, double level_2, double target_level) { double angstrom_log = -log10(value_1/value_2)/log10(level_1/level_2); double angstrom_value = value_2 * pow((target_level/level_2),-angstrom_log); return angstrom_value; } + +//////////////////////////////////////////////////////////////////////// diff --git a/src/tools/other/ascii2nc/airnow_handler.cc b/src/tools/other/ascii2nc/airnow_handler.cc index 2eb467ee8c..fbc655f9dd 100644 --- a/src/tools/other/ascii2nc/airnow_handler.cc +++ b/src/tools/other/ascii2nc/airnow_handler.cc @@ -84,8 +84,6 @@ const string hdr_hourlyaqobs_co_units = "CO_Unit"; const string hdr_hourlyaqobs_so2 = "SO2"; const string hdr_hourlyaqobs_so2_units = "SO2_Unit"; -const float AIRNOW_MISSING_VALUE = -999.; - string remove_quotes(string &s); bool doubleOrMissing(const string &s, double &value); vector parseHourlyAqobsLine(const string &asciiLine, bool &ok); @@ -309,7 +307,7 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, col = _extractColumn(data_line, elevPtr); elev = atof(col.c_str()); } else { - elev = AIRNOW_MISSING_VALUE; + elev = bad_data_double; } } string varName; @@ -317,8 +315,6 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, double value; int aqiValue; int aqiCategory; - //double height_m = AIRNOW_MISSING_VALUE; // maybe change - // go with this for now, can easily replace with previous line double height_m = elev; if (format_version == AIRNOW_FORMAT_VERSION_DAILYV2) { @@ -333,7 +329,7 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, // for now only the single variable is written as an observation _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varName)); } else if (format_version == AIRNOW_FORMAT_VERSION_HOURLY) { varName = _extractColumn(data_line, varnamePtr); @@ -342,7 +338,7 @@ bool AirnowHandler::_parseObservationLineStandard(DataLine &data_line, value = atof(col.c_str()); _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varName)); } return true; @@ -422,7 +418,7 @@ bool AirnowHandler::_parseObservationLineAqobs(const string &data_line, if (elevPtr >= 0) { elev = atof(tokens[elevPtr].c_str()); } else { - elev = 0.0; // or maybe -99 missing + elev = 0.0; } _addHourlyAqobsObs(tokens, header_type, stationId, valid_time, lat, lon, elev, @@ -493,8 +489,6 @@ void AirnowHandler::_addHourlyAqobsObs(const vector &data_line, const st int aqi; double value; string units; - // double height_m = AIRNOW_MISSING_VALUE; // maybe change - // go with this, can easily switch to previous line double height_m = elev; status = atoi(data_line[measuredPtr].c_str()); @@ -505,7 +499,7 @@ void AirnowHandler::_addHourlyAqobsObs(const vector &data_line, const st // for now only the single variable is written as an observation _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varname)); } } @@ -522,15 +516,13 @@ void AirnowHandler::_addHourlyAqobsObs(const vector &data_line, const st string col; double value; string units; - // double height_m = AIRNOW_MISSING_VALUE; // maybe change - // go with this, can easily switch to previous line double height_m = elev; if (doubleOrMissing(data_line[valuePtr], value)) { units = data_line[unitPtr]; // ignored for now _addObservations(Observation(header_type, stationId, valid_time, lat, lon, elev, na_str, 0, - AIRNOW_MISSING_VALUE, height_m, + bad_data_double, height_m, value, varname)); } } @@ -923,7 +915,7 @@ string remove_quotes(string &s) bool doubleOrMissing(const string &s, double &value) { if (s.empty()) { - value = AIRNOW_MISSING_VALUE; + value = bad_data_double; return false; } else { value = atof(s.c_str()); @@ -964,3 +956,5 @@ vector parseHourlyAqobsLine(const string &asciiLine, bool &ok) } return tokens; } + +////////////////////////////////////////////////////////////////////////