diff --git a/src/tools/core/ensemble_stat/ensemble_stat.cc b/src/tools/core/ensemble_stat/ensemble_stat.cc index a9ebe8efb5..7d319c7cfd 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat.cc @@ -69,7 +69,9 @@ // 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. // 039 09/29/22 Halley Gotway MET #2286 Refine GRIB1 table lookup logic. -// 040 10/03/22 Prestopnik MET #2227 Remove using namespace netCDF from header files +// 040 10/03/22 Prestopnik MET #2227 Remove using namespace netCDF from +// header files +// 041 04/16/24 Halley Gotway MET #2786 Compute RPS from climo bin probs. // //////////////////////////////////////////////////////////////////////// @@ -2059,6 +2061,9 @@ void write_txt_files(const EnsembleStatVxOpt &vx_opt, int i, j; PairDataEnsemble pd; + // Check for probabilistic input + bool is_prob = vx_opt.vx_pd.fcst_info->get_var_info()->is_prob(); + // Process each observation filtering threshold for(i=0; iget_var_info()->is_prob(); - // Compute ECNT scores - if(vx_opt.output_flag[i_ecnt] != STATOutputType::None && - !is_prob) { + if(!is_prob && + vx_opt.output_flag[i_ecnt] != STATOutputType::None) { do_ecnt(vx_opt, vx_opt.othr_ta[i], &pd); } - // Compute RPS scores + // Compute RPS scores, only support for forecast probabilities if(vx_opt.output_flag[i_rps] != STATOutputType::None) { do_rps(vx_opt, vx_opt.othr_ta[i], &pd); } // Write RHIST counts - if(vx_opt.output_flag[i_rhist] != STATOutputType::None && - !is_prob) { + if(!is_prob && + vx_opt.output_flag[i_rhist] != STATOutputType::None) { pd.compute_rhist(); @@ -2103,8 +2105,8 @@ void write_txt_files(const EnsembleStatVxOpt &vx_opt, } // Write PHIST counts if greater than 0 - if(vx_opt.output_flag[i_phist] != STATOutputType::None && - !is_prob) { + if(!is_prob && + vx_opt.output_flag[i_phist] != STATOutputType::None) { pd.phist_bin_size = vx_opt.vx_pd.pd[0][0][0].phist_bin_size; pd.compute_phist(); @@ -2118,8 +2120,8 @@ void write_txt_files(const EnsembleStatVxOpt &vx_opt, } // Write RELP counts - if(vx_opt.output_flag[i_relp] != STATOutputType::None && - !is_prob) { + if(!is_prob && + vx_opt.output_flag[i_relp] != STATOutputType::None) { pd.compute_relp(); @@ -2132,8 +2134,8 @@ void write_txt_files(const EnsembleStatVxOpt &vx_opt, } // Write SSVAR scores - if(vx_opt.output_flag[i_ssvar] != STATOutputType::None && - !is_prob) { + if(!is_prob && + vx_opt.output_flag[i_ssvar] != STATOutputType::None) { pd.ssvar_bin_size = vx_opt.vx_pd.pd[0][0][0].ssvar_bin_size; pd.compute_ssvar(); @@ -2163,16 +2165,17 @@ void write_txt_files(const EnsembleStatVxOpt &vx_opt, } // end for i // Write PCT counts and scores - if(vx_opt.output_flag[i_pct] != STATOutputType::None || - vx_opt.output_flag[i_pstd] != STATOutputType::None || - vx_opt.output_flag[i_pjc] != STATOutputType::None || - vx_opt.output_flag[i_prc] != STATOutputType::None || - vx_opt.output_flag[i_eclv] != STATOutputType::None) { + if(!is_prob && + (vx_opt.output_flag[i_pct] != STATOutputType::None || + vx_opt.output_flag[i_pstd] != STATOutputType::None || + vx_opt.output_flag[i_pjc] != STATOutputType::None || + vx_opt.output_flag[i_prc] != STATOutputType::None || + vx_opt.output_flag[i_eclv] != STATOutputType::None)) { do_pct(vx_opt, pd_all); } // Write out the unfiltered ORANK lines for point verification - if(is_point_vx && + if(is_point_vx && !is_prob && vx_opt.output_flag[i_orank] != STATOutputType::None) { // Set the header column 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 c6d991005f..8306e3f41e 100644 --- a/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc +++ b/src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc @@ -801,8 +801,9 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict, fcat_ta = fdict.lookup_thresh_array(conf_key_prob_cat_thresh); ocat_ta = odict.lookup_thresh_array(conf_key_prob_cat_thresh); - // The number of thresholds must match - if(fcat_ta.n() != ocat_ta.n()) { + // The number of thresholds must match for non-probability forecasts + if(!vx_pd.fcst_info->get_var_info()->is_prob() && + fcat_ta.n() != ocat_ta.n()) { mlog << Error << "\nEnsembleStatVxOpt::process_config() -> " << "The number of forecast (" << write_css(fcat_ta) << ") and observation (" << write_css(ocat_ta)