Skip to content

Commit

Permalink
Feature #2795 level_mismatch_warning (#2873)
Browse files Browse the repository at this point in the history
* Per #2795, move the warning message about level mismatch from the config validation step to when the forecast files are being processed. Only check this when the number of forecast fields is greater than 1, but no longer limit the check to pressure levels only.

* Per #2795, add comments

* Whitespace

* Per #2795, port level mismatch fix over to Ensemble-Stat. Check it for each verification task, but only print it once for each task, rather than once for each task * ensemble member.
  • Loading branch information
JohnHalleyGotway authored Apr 30, 2024
1 parent 3caffb4 commit d3ecc87
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 65 deletions.
34 changes: 27 additions & 7 deletions src/tools/core/ensemble_stat/ensemble_stat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@
// 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
// header files.
// 041 04/16/24 Halley Gotway MET #2786 Compute RPS from climo bin probs.
// 042 04/29/24 Halley Gotway MET #2795 Move level mismatch warning.
//
////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -839,6 +840,10 @@ void process_point_vx() {
// Loop through each of the fields to be verified
for(i=0; i<conf_info.get_n_vx(); i++) {

VarInfo *fcst_info = conf_info.vx_opt[i].vx_pd.fcst_info->get_var_info();
VarInfo *obs_info = conf_info.vx_opt[i].vx_pd.obs_info;
bool print_level_mismatch_warning = true;

// Initialize
emn_dpa.clear();

Expand All @@ -857,6 +862,23 @@ void process_point_vx() {
continue;
}

// MET #2795, for multiple individual forecast levels, print a
// warning if the observations levels are not fully covered.
if(print_level_mismatch_warning &&
fcst_dpa.n_planes() > 1 &&
!is_eq(fcst_info->level().lower(), fcst_info->level().upper()) &&
(obs_info->level().lower() < fcst_info->level().lower() ||
obs_info->level().upper() > fcst_info->level().upper())) {
mlog << Warning << "\nprocess_point_vx() -> "
<< "The forecast level range (" << fcst_info->magic_str()
<< ") does not fully contain the observation level range ("
<< obs_info->magic_str() << "). No vertical interpolation "
<< "will be performed for observations falling outside "
<< "the range of forecast levels. Instead, they will be "
<< "matched to the single nearest forecast level.\n\n";
print_level_mismatch_warning = false;
}

// Store ensemble member data
conf_info.vx_opt[i].vx_pd.set_fcst_dpa(fcst_dpa);

Expand All @@ -875,20 +897,18 @@ void process_point_vx() {
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();

// 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)) {
if(!get_data_plane_array(ens_mean_file.c_str(), fcst_info->file_type(),
fcst_info, emn_dpa, true)) {
mlog << Error << "\nprocess_point_vx() -> "
<< "trouble reading the ensemble mean field \""
<< info->magic_str() << "\" from file \""
<< fcst_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()
mlog << Debug(2) << "For " << fcst_info->magic_str()
<< " found " << emn_dpa.n_planes() << " forecast levels.\n";

}
Expand Down
19 changes: 0 additions & 19 deletions src/tools/core/ensemble_stat/ensemble_stat_conf_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -710,25 +710,6 @@ void EnsembleStatVxOpt::process_config(GrdFileType ftype, Dictionary &fdict,
vx_pd.obs_info->dump(cout);
}

// Check the levels for the forecast and observation fields. If the
// forecast field is a range of pressure levels, check to see if the
// range of observation field pressure levels is wholly contained in the
// fcst levels. If not, print a warning message.
if(vx_pd.fcst_info->get_var_info()->level().type() == LevelType_Pres &&
!is_eq(vx_pd.fcst_info->get_var_info()->level().lower(), vx_pd.fcst_info->get_var_info()->level().upper()) &&
(vx_pd.obs_info->level().lower() < vx_pd.fcst_info->get_var_info()->level().lower() ||
vx_pd.obs_info->level().upper() > vx_pd.fcst_info->get_var_info()->level().upper())) {

mlog << Warning
<< "\nEnsembleStatVxOpt::process_config() -> "
<< "The range of requested observation pressure levels "
<< "is not contained within the range of requested "
<< "forecast pressure levels. No vertical interpolation "
<< "will be performed for observations falling outside "
<< "the range of forecast levels. Instead, they will be "
<< "matched to the single nearest forecast level.\n\n";
}

// No support for wind direction
if(vx_pd.fcst_info->get_var_info()->is_wind_direction() ||
vx_pd.obs_info->is_wind_direction()) {
Expand Down
52 changes: 32 additions & 20 deletions src/tools/core/point_stat/point_stat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@
// 050 02/11/22 Halley Gotway MET #2045 Fix HiRA output.
// 051 07/06/22 Howard Soh METplus-Internal #19 Rename main to met_main
// 052 09/29/22 Halley Gotway MET #2286 Refine GRIB1 table lookup logic.
// 053 10/03/22 Prestopnik MET #2227 Remove using namespace netCDF from header files
// 053 10/03/22 Prestopnik MET #2227 Remove using namespace netCDF from header files.
// 054 04/29/24 Halley Gotway MET #2795 Move level mismatch warning.
//
////////////////////////////////////////////////////////////////////////

Expand Down Expand Up @@ -606,45 +607,56 @@ void process_fcst_climo_files() {
// the forecast and climatological fields for verification
for(int i=0; i<conf_info.get_n_vx(); i++) {

VarInfo *fcst_info = conf_info.vx_opt[i].vx_pd.fcst_info;
VarInfo *obs_info = conf_info.vx_opt[i].vx_pd.obs_info;

// Read the gridded data from the input forecast file
n_fcst = fcst_mtddf->data_plane_array(
*conf_info.vx_opt[i].vx_pd.fcst_info, fcst_dpa);
mlog << Debug(2)
<< "\n" << sep_str << "\n\n"
<< "Reading data for "
<< conf_info.vx_opt[i].vx_pd.fcst_info->magic_str()
<< ".\n";
n_fcst = fcst_mtddf->data_plane_array(*fcst_info, fcst_dpa);
mlog << Debug(2) << "\n" << sep_str << "\n\n"
<< "Reading data for " << fcst_info->magic_str() << ".\n";

// Check for zero fields
if(n_fcst == 0) {
mlog << Warning << "\nprocess_fcst_climo_files() -> "
<< "no fields matching "
<< conf_info.vx_opt[i].vx_pd.fcst_info->magic_str()
<< " found in file: "
<< fcst_file << "\n\n";
<< "no fields matching " << fcst_info->magic_str()
<< " found in file: " << fcst_file << "\n\n";
continue;
}

// MET #2795, for multiple individual forecast levels, print a
// warning if the observations levels are not fully covered.
if(n_fcst > 1 &&
!is_eq(fcst_info->level().lower(), fcst_info->level().upper()) &&
(obs_info->level().lower() < fcst_info->level().lower() ||
obs_info->level().upper() > fcst_info->level().upper())) {
mlog << Warning << "\nprocess_fcst_climo_files() -> "
<< "The forecast level range (" << fcst_info->magic_str()
<< ") does not fully contain the observation level range ("
<< obs_info->magic_str() << "). No vertical interpolation "
<< "will be performed for observations falling outside "
<< "the range of forecast levels. Instead, they will be "
<< "matched to the single nearest forecast level.\n\n";
}

// Setup the first pass through the data
if(is_first_pass) setup_first_pass(fcst_dpa[0], fcst_mtddf->grid());

// Regrid, if necessary
if(!(fcst_mtddf->grid() == grid)) {
mlog << Debug(1)
<< "Regridding " << fcst_dpa.n_planes()
<< " forecast field(s) for "
<< conf_info.vx_opt[i].vx_pd.fcst_info->magic_str()
<< " forecast field(s) for " << fcst_info->magic_str()
<< " to the verification grid.\n";

// Loop through the forecast fields
for(j=0; j<fcst_dpa.n_planes(); j++) {
fcst_dpa[j] = met_regrid(fcst_dpa[j], fcst_mtddf->grid(), grid,
conf_info.vx_opt[i].vx_pd.fcst_info->regrid());
fcst_info->regrid());
}
}

// Rescale probabilities from [0, 100] to [0, 1]
if(conf_info.vx_opt[i].vx_pd.fcst_info->p_flag()) {
if(fcst_info->p_flag()) {
for(j=0; j<fcst_dpa.n_planes(); j++) {
rescale_probability(fcst_dpa[j]);
}
Expand Down Expand Up @@ -685,8 +697,8 @@ void process_fcst_climo_files() {

// Dump out the number of levels found
mlog << Debug(2)
<< "For " << conf_info.vx_opt[i].vx_pd.fcst_info->magic_str()
<< " found " << n_fcst << " forecast levels, "
<< "For " << fcst_info->magic_str() << " found "
<< n_fcst << " forecast levels, "
<< cmn_dpa.n_planes() << " climatology mean levels, and "
<< csd_dpa.n_planes() << " climatology standard deviation levels.\n";

Expand Down Expand Up @@ -1825,8 +1837,8 @@ void do_hira_ens(int i_vx, const PairDataPoint *pd_ptr) {
conf_info.vx_opt[i_vx].hira_info.width[i],
grid.wrap_lon());
if (nullptr == gt) {
mlog << Warning
<< "\nPdo_hira_ens() Fail to get GridTemplate for " << i << "-th width.\n\n";
mlog << Warning << "\ndo_hira_ens() -> "
<< "failed to get GridTemplate for " << i << "-th width.\n\n";
continue;
}

Expand Down
19 changes: 0 additions & 19 deletions src/tools/core/point_stat/point_stat_conf_info.cc
Original file line number Diff line number Diff line change
Expand Up @@ -851,25 +851,6 @@ void PointStatVxOpt::process_config(GrdFileType ftype,
vx_pd.obs_info->dump(cout);
}

// Check the levels for the forecast and observation fields. If the
// forecast field is a range of pressure levels, check to see if the
// range of observation field pressure levels is wholly contained in the
// fcst levels. If not, print a warning message.
if(vx_pd.fcst_info->level().type() == LevelType_Pres &&
!is_eq(vx_pd.fcst_info->level().lower(), vx_pd.fcst_info->level().upper()) &&
(vx_pd.obs_info->level().lower() < vx_pd.fcst_info->level().lower() ||
vx_pd.obs_info->level().upper() > vx_pd.fcst_info->level().upper())) {

mlog << Warning
<< "\nPointStatVxOpt::process_config() -> "
<< "The range of requested observation pressure levels "
<< "is not contained within the range of requested "
<< "forecast pressure levels. No vertical interpolation "
<< "will be performed for observations falling outside "
<< "the range of forecast levels. Instead, they will be "
<< "matched to the single nearest forecast level.\n\n";
}

// No support for wind direction
if(vx_pd.fcst_info->is_wind_direction() ||
vx_pd.obs_info->is_wind_direction()) {
Expand Down

0 comments on commit d3ecc87

Please sign in to comment.